INSERT INTO SELECT gestion des erreurs

J'écris une procédure stockée T-SQL à insert dans une table en utilisant l'instruction

INSERT INTO [tableName] ..... SELECT * FROM [tableName] 

Parfois, la table d'input (SELECT) peut contenir des valeurs incorrectes: la table où l'insertion attend une décimale et la sélection renvoient une valeur NVarChar qui provoquera une erreur de conversion. Maintenant, parce que l'instruction fait un "bulk insert", je ne sais pas quel est le dernier logging inséré ou quel est l'logging qui contient les mauvaises données. SQL dit seulement "erreur de conversion …" Yat-il un moyen de "connecter" le dernier logging inséré de sorte que je sais au less quelle ligne contient la mauvaise valeur? (sans utiliser de sliders)

Observez le résultat de cette requête

 SELECT v.id, v.val, x=TRY_CAST(v.val AS DECIMAL(28,2)) FROM (VALUES(1,'1.26'),(2,'A.13')) AS v(id,val) WHERE TRY_CAST(v.val AS DECIMAL(28,2)) IS NULL 

Résultats:

 +----+------+------+ | id | val | x | +----+------+------+ | 2 | A.13 | NULL | +----+------+------+ 

Il utilise TRY_CAST , qui renvoie NULL si le CAST échoué. Vous pouvez l'utiliser pour déterminer les loggings qui échouent ou pour limiter l'set que vous insérez dans la table cible.

Il n'y a pas de dernière erreur.

Selon les conditions ACID de database de base, l'instruction est ATOMIC – elle fonctionne complètement ou échoue complètement. Il n'y a pas non plus d'ordre défini dans lequel les lignes sont traitées en interne – cela peut varier en fonction des caractéristiques du server et des données.

Généralement, vous désinfectez datatables avant de les copyr dans la table cible.

Vous pouvez essayer d'utiliser la clause OUTPUT afin de sortir les lignes insérées jusqu'à ce qu'il rencontre l'erreur. Vous pouvez également utiliser un ORDER BY afin qu'il soit plus rapide de déterminer exactement quelle est la ligne suivante pour laquelle l'insertion échoue. Puis, connaissant la ligne qui échoue, il devrait être plus facile de déterminer le champ avec le problème.

Lien MSDN

Une instruction UPDATE, INSERT ou DELETE qui a une clause OUTPUT returnnera des lignes au client même si l'instruction rencontre des erreurs et est annulée. Le résultat ne doit pas être utilisé si une erreur se produit lorsque vous exécutez l'instruction.

Vous pouvez utiliser ci-dessous déclaration que la colonne est en train de faire un problème de conversion.

 SELECT SQL_VARIANT_PROPERTY(col1, 'BaseType') from Table1 

Pour filterr le problème

 SELECT * from Table1 WHERE QL_VARIANT_PROPERTY(col1, 'BaseType') not like 'decimal%' 

J'ai déjà fait face à ce problème avec l'import de 15 millions de lignes dans une table. Nous avons finalement décidé qu'il était mieux fait dans SSIS avec l'approche suivante:

  1. Créer permet de dire n tâches de données avec l'une suivant l'autre "ON ERROR" seulement
  2. Dans la première tâche de données, réglez batch comme 100K. Et en cas d'erreur, allez à la prochaine que nous avons nommé 10K
  3. Dans cette tâche, qui est 10K, nous passons COMMIT batch à 10K et "ON ERROR" nous allons à 1K et ainsi de suite.
  4. Nous finissons par, sur la tâche de données COMMIT BATCH record "ON ERROR", déplacer datatables dans une table (appelez la table ERROR RECORD) qui a assez de colonnes (toutes VARCHAR / NVARCHAR) pour contenir datatables entrantes + une colonne supplémentaire pour contenir SSIS Message d'erreur pour cette ligne.

Plus tard, lorsque le SSIS sera terminé, nous parsingrons tous les loggings qui ont échoué. De cette façon, disons que vous avez seulement 5 erreurs sur 15 millions, nous aurions 1494995 loggings avec succès et 5 loggings dans la table de quarantaine.

Merci et j'espère que cette approche vous aidera