0
votes

BCP Valeur Char au flocon de neige

J'essaye de créer un fichier BCP avec | délimiteur, puis chargez-le dans une table de flocon de neige.

Problème: dans le serveur SQL, il y a des colonnes définies comme CHAR (4) et ont des valeurs "sss" donc quand je fais BCP, il est rembourré à une longueur de 4 "sss" et chargé en flocon de neige en raison de laquelle nos rapports échouent car ils font quelque chose comme where column = "SSS" mais en raison de l'espace de fin dans le flocon de neige, les colonnes correctes ne s'affichent pas.

nous ne voulons pas modifier nos rapports. Alors, y a-t-il un moyen pour BCP de gérer le remplissage ou le rognage de ces colonnes?

notez qu'il y a 24 tables et chacune a environ 130 + colonnes, donc je ne peux pas aller et mettre des fonctions Trim sur chaque colonne de caractères


4 commentaires

Que diriez-vous de définir le type comme étant varchar (4) dans SQL Server, Snowflake ou les deux?


Votre question est-elle que l'espace de fin n'est pas inclus dans le fichier BCP, ou que Snowflake supprime l'espace de fin lorsqu'il est chargé dans Snowflake?


Cela s'avère être un problème car la sémantique de Snowflake CHAR diffère des autres bases de données.


Le titre de ceci devrait-il être quelque chose comme ... "BCP ajoutant des espaces aux données avant le chargement dans Snowflake"?


3 Réponses :


2
votes

Si votre fichier BCP conserve l'espace de fin, Snowflake le conservera également, tant que le champ est FIELD_OPTIONALLY_ENCLOSED_BY a "ou". Vous pouvez également vous assurer que votre option TRIM_SPACE est correctement définie sur votre format définition de votre commande COPY INTO.

Si votre fichier BCP ne maintient pas l'espace et que vous ne pouvez pas comprendre comment le faire fonctionner, vous pouvez forcer l'espace à revenir lors de la commande COPY INTO avec certaines fonctions de chaîne dans votre SELECT, ou vous pouvez créer une vue pour votre rapport qui exécute le même ensemble de fonctions de chaîne pour forcer l'espace à partir duquel votre rapport fonctionne.


1 commentaires

BCP maintient l'espace de fin, ce qu'il devrait. L'utilisation de TRIM_SPACE devrait être un bon moyen de résoudre les problèmes de rapport.



0
votes

Il s'agit d'un "problème" connu avec BCP . La "solution" est d'utiliser l'option queryout , ce qui signifie que vous devez inclure une requête à chaque exportation. Mais les données sont telles qu'elles sont.

Par exemple: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/88c258fe-d1a6-4f3a- 9dac-40388d04e9c7 / remove-space-in-columns-on-bcp-out? Forum = transactsql

Mais c'est vraiment un problème de Snowflake, car Snowflake a son propre CHAR par défaut sémantique.
Vous obtenez un avertissement dans la documentation Types de données chaîne et binaires a> mais cela ne dit pas toute la vérité.

Ce qui suit exécuté sur Oracle (et apparemment MSSQL? MySQL?) sélectionnera la ligne aaa :

XXX

mais pas sur Snowflake, sauf si vous créez la colonne avec COLLATION:

CREATE OR REPLACE TABLE C (t CHAR(4) COLLATE 'en_US-rtrim');
INSERT INTO C VALUES('aaa ');
SELECT * FROM C WHERE t = 'aaa';

Malheureusement, vous impossible de ALTER le classement après la création, ce qui aurait été pratique après un COPY INTO

.

PS: strong> La réponse de Mike Walton est meilleure, TRIM_SPACE est beaucoup plus propre que COLLATE.


6 commentaires

Ce n'est pas un "problème" avec BCP. Le type est CHAR () . Les CHAR () sont remplis d'espaces.


Je suis d'accord, d'où mes citations. Il s'agit de savoir si la sémantique CHAR par défaut est différente sur Snowflake.


le problème de l'affiche n'est pas "aaa" ... sa valeur est "aaa". Son problème est qu'il copie forcer 4 octets de données ... pas qu'un octet supplémentaire soit réellement inclus dans les données. Il est difficile de critiquer Snowflake ici quand la valeur réelle est "aaa" et non "aaa". C'est un fichier délimité ... il n'y a pas besoin de champs de largeur fixe.


Les valeurs sont les mêmes dans les deux bases de données, c'est-à-dire «aaa». Les deux bases de données se comportent différemment, la comparaison 'aaa' = 'aaa' renvoie TRUE dans la base de données d'origine, mais FALSE dans Snowflake. Mais lors de la configuration de COLLATE pour la colonne Snowflake, 'aaa' = 'aaa' renvoie également TRUE dans Snowflake. Une deuxième option consiste à couper les chaînes lors de l'importation dans Snowflake, en espérant que cela ne casse rien d'autre.


les états originaux de l'affiche ... ont des valeurs "sss" donc quand je fais BCP le son étant rempli à la longueur de 4 "sss" .... la base de données source a seulement 3 octets de données. le 4e est introduit par la copie. Les deux bases de données se comportent différemment comme vous le dites ... je ne m'adresse pas à cela. J'essaie simplement de souligner que c'est la copie qui introduit l'octet en raison du choix du type de données. Les données elles-mêmes sont très bien.


L'affiche originale dit que sa colonne d'origine est CHAR (4), et cela signifie que même s'il exécute UPDATE .. SET my_column = 'sss', la chaîne est remplie d'espace à la longueur 4. Cela se produit dans la plupart des bases de données, mais pas par défaut dans Snowflake , et cela peut créer un problème lors du portage vers Snowflake. Si Snowflake avait une collation rtrim par défaut des données CHAR comme le font les autres bases de données, il n'y aurait aucun problème de portage.



0
votes

Alors, y a-t-il un moyen pour BCP de gérer le remplissage ou le rognage de ces colonnes?

Oui, mais pas par un commutateur ou une option. La bonne façon de gérer cela est de définir vos types de données à l'avance. Comme quelqu'un l'a mentionné dans les commentaires de votre question, votre requête qui crée une sortie BCP doit utiliser VARCHAR (4) au lieu de CHAR (4). BCP vous donne ce que vous lui avez demandé. Leur façon d'éviter les espaces est d'utiliser varchar.

On dirait qu'une "recherche et remplacement" assez rapide par rapport aux objets de requête scriptés fonctionnerait bien, mais vous connaissez mieux votre situation.

De plus, "trim" ne fonctionnera pas - FYI. Même si la valeur du champ était uniquement "SSS" (comme dans votre exemple); si le résultat / colonne est défini comme CHAR (4), vous obtiendrez 4 octets de données et un espace vide à la 4ème place puisque vous n'aviez que 3 octets de données. Le découpage fonctionnera pendant la requête ... le "" rembourré que vous obtenez est placé là par la copie. La manière de corriger cela est de définir vos types de données selon vos besoins dès le départ.

À moins que quelqu'un ne connaisse une meilleure façon de faire du snowflake (je ne le connais pas), la seule autre option est de manipuler le fichier entre SQL et Snowflake. remplacer "|" avec "|" ... mais ... blech.


2 commentaires

La redéfinition des types de données peut être une option pour une petite solution locale, mais pas pour la plupart. Vous avez raison de dire que BCP queryout trim () ne fonctionnera probablement pas (non sans une conversion en VARCHAR), mais la solution de contournement la plus élégante serait d'utiliser l'option TRIM_SPACE pour COPY INTO comme le suggère Mike Walton dans sa réponse.


Les types de données peuvent être définis avec DDL ou simplement en effectuant un cast dans une vue / requête qui interroge réellement les données. Cela peut être fait dans une solution locale ou d'entreprise. En fait, je trouve que c'est beaucoup plus probable dans la solution d'entreprise où vous avez plus que probablement un accès direct aux données sources. Mais d'accord, s'il existe un moyen propre et rapide de gérer cela à destination, alors faites-le. Je réponds directement à la question des affiches sur SQL Server BCP.