2009-07-07 6 views
5

SQL Server 2005 Question:SQL Server: Découvrez ce que la ligne a provoqué la TSQL échec (SSIS)

Je travaille sur un projet de conversion de données où je prends 80k + lignes et en les déplaçant d'une table à un autre. Quand je lance le TSQL, il bombarde avec diverses erreurs liées à la conversion de types, ou peu importe. Y at-il un moyen de savoir quelle ligne a provoqué l'erreur?

=====================

MISE À JOUR:

je joue un INSERT INTO TABLE1 (...) SELECT. .. FROM TABLE2 Table2 est juste un tas de champs varchar où TABLE1 a les bons types.

Ce script sera placé dans un sproc et exécuté à partir d'un package SSIS. Le package SSIS importe d'abord 5 grands fichiers plats dans TABLE2.

Voici un exemple de message d'erreur: "La conversion d'un type de données char en un type de données datetime a abouti à une valeur de date-heure hors plage."

Il existe plusieurs champs de date. Dans TABLE2, il existe des valeurs de données telles que "02/05/1075" pour Birthdate. Je veux examiner chaque rangée qui cause l'erreur, ainsi je peux rapporter au département responsable des mauvaises données ainsi elles peuvent le corriger.

+0

Pouvez-vous nous donner quelques exemples de l'erreur? Comment déplacez-vous les données, avec une instruction d'insertion ou des curseurs? À ma connaissance, il n'y a pas vraiment de fichier journal qui vous dira exactement quelle est l'erreur, mais peut-être qu'avec des messages d'erreur, nous pouvons vous orienter dans la bonne direction. – OhioDude

+0

S'il vous plaît prêter plus d'attention à vos choix de balises. –

+1

S'il s'agit d'un cast, il y a des fonctions ISNUMERIC et ISDATE pour aider à tester si une chaîne peut implicitement réussir la conversion en un nombre ou une date, respectivement. ISNUMERIC a cependant un défaut en ce qui concerne les virgules et les espaces, selon mon expérience. Mais oui, votre OP devrait être beaucoup plus précis sur les erreurs que vous rencontrez. –

Répondre

3

Ce que j'est divisé en deux l'ensemble de lignes avec une clause WHERE:

INSERT MyTable(id, datecol) SELECT id, datecol FROM OtherTable WHERE ID BETWEEN 0 AND 40,000 

puis continuer à changer les valeurs de la entre une partie de la clause where. Je l'ai fait à la main plusieurs fois, mais il me semble que vous pouvez automatiser le fractionnement avec un petit code .Net en boucle, en piégeant les exceptions et en le réduisant à la ligne qui lance l'exception, petit à petit.

+4

Syntaxe incorrecte et mauvaise idée pour résoudre le problème. Cela fonctionnera (une fois l'erreur de syntaxe corrigée) mais c'est le moins efficace et il faut vraiment le faire à la main plutôt que de l'exécuter dans un paquet. Les dates incorrectes sont facilement identifiables à l'aide de la fonction isdate(). – HLGEM

+0

Correction du mauvais SQL. –

0

Si vous travaillez avec des curseurs, oui et est trivial. Si vous ne travaillez pas avec des curseurs, je ne pense pas car les opérations SQL sont ACID, ou des transactions en soi.

2

Je suppose que vous faites la mise à jour avec l'instruction INSERT INTO ...

Essayez plutôt de faire la mise à jour avec le curseur, sauf l'utilisation de manutention pour attraper l'erreur et connectez-vous tout ce que vous devez: le numéro de la ligne, il a échoué sur

+2

convenir 80k lignes n'est pas si grand que le curseur y arrivera; S'il y a plus d'une erreur, cela aidera. N'oubliez pas que vous pouvez essayer/attraper dans sql 2005 afin que vous puissiez stocker les lignes qui ont échoué et continuer avec ceux qui ont fonctionné. – u07ch

+1

bon point, u07ch: insérez tout ce qui n'a pas jeté l'erreur, alors vous pouvez simplement LEFT JOIN ... OERE RIGHT.X est NULL pour vérifier ceux qui n'ont pas été insérés dans une seule déclaration. S'il y a beaucoup de lignes qui échouent, ce serait la meilleure solution plutôt que de fixer 1K lignes erronées sur 80K. Mais très probablement, il suffit de trouver 1-2 causes différentes, les autres devraient être les mêmes et devraient être faciles à résoudre. – van

1

Si vous faites une boucle, ajoutez des impressions dans la boucle. Si vous utilisez des opérations basées sur un ensemble, ajoutez une condition WHERE restrictive et exécutez-la. Continuez à l'exécuter (à chaque fois en le rendant de plus en plus restrictif) jusqu'à ce que vous puissiez trouver la ligne dans les données. Si vous pouviez l'exécuter pour des blocs de N lignes, sélectionnez simplement ces lignes et regardez-les.

instructions CASE ADD pour attraper les problèmes (conversion de cette mauvaise valeur NULL ou Whetever) et mettre une valeur dans une nouvelle FlagColumn vous dire le type de problème:

CASE WHEN ISNUMERIC(x)!=1 then NULL ELSE x END as x 
,CASE WHEN ISNUMERIC(x)!=1 then 'not numeric' else NULL END AS FlagColumn 

puis sélectionnez la nouvelle données converties où FlagColumn IS NOT NULL

vous pouvez essayer d'utiliser des instructions de sélection des fonctions IsNumeric() ou IsDate() sur les différentes colonnes des données source

EDIT

Il existe plusieurs champs de date. Dans le TABLEAU 2, , il existe des valeurs de données telles que '02/05/1075 'pour Birthdate. Je veux examiner chaque ligne qui provoque l'erreur , donc je peux signaler au département responsable des mauvaises données afin qu'ils puissent le corriger.

Utilisez cette option pour retourner toutes les mauvaises lignes de date:

SELECT * FROM YourTable WHERE ISDATE(YourDateColumn)!=1 
5

Ce n'est pas la façon de le faire avec SSIS. Vous devriez avoir les flux de données de votre source, à votre destination, avec toutes les transformations dont vous avez besoin au milieu. Vous serez en mesure d'obtenir des détails d'erreur, et en fait, des lignes d'erreur en utilisant la sortie d'erreur de la destination. J'envoie souvent la sortie d'erreur d'une destination vers une autre destination - un fichier texte ou une table configurée pour tout autoriser, y compris des données qui n'auraient pas été valides dans la destination réelle.


En fait, si vous le faites de façon standard dans SSIS, puis discordances de type de données doivent être détectées au moment de la conception.

0

John Sauders a la bonne idée, il existe de meilleures façons de faire ce genre de traitement en utilisant SSIS. Cependant, apprendre SSIS et refaire votre paquet pour complètement changer le processus peut ne pas être une option en ce moment, donc j'offre ce conseil. Vous semblez avoir des problèmes avec les dates étant incorrectes. Donc, lancez d'abord une requête pour identifier les enregistrements qui sont mauvais et insérez-les dans une table execptions. Insérez-vous ensuite uniquement les enregistrements restants. Quelque chose comme:

insert exceptiontable (field1, field2) 
select field1, field2 from table2 where isdate(field2) = 0 

insert table1 (field1, field2) 
select field1, field2 from table2 where isdate(field2) = 1 

Ensuite, vous pouvez bien sûr envoyer le contenu de la table d'exception aux personnes qui fournissent les mauvaises données.

+0

Il a dit qu'il utilisait déjà SSIS, et Source -> Dest -> Erreur n'est pas très difficile ... –

+0

Je suis d'accord, c'est comme ça que je le ferais, mais SSIS n'est pas facile à apprendre à utiliser correctement et il peut être sous la pression du temps. Je sais que je viens de faire des paquets DTS pendant des années, cette méthode ne m'est jamais venue à l'esprit si je n'avais pas eu de formation formelle sur SSIS. Il utilise clairement les scripts t-sql et non le flux de données, il peut donc ne pas savoir comment utiliser le flux de données. Ce n'est pas facile la première fois que vous le faites. – HLGEM

+0

Vous savez, il ne m'est jamais venu à l'esprit qu'il pourrait utiliser SSIS et ne pas utiliser un flux de données. –

2

Pas exactement un curseur, mais aussi efficace - J'avais plus de 4 millions de lignes à examiner avec plusieurs échecs de conversion. Voici ce que j'ai utilisé, et il en résulte deux tables temporaires avec toutes mes valeurs et lignes assignées et une qui contient simplement une liste de lignes dans la première table temporaire qui n'a pas pu être convertie.

select row_number() over (order by TimeID) as rownum,timeID into #TestingTable from MyTableWithBadData 

set nocount on 
declare @row as int 
declare @last as int 
set @row=0 
select @last = count(*) from #TestingTable 
declare @timeid as decimal(24,0) 
create table #fails (rownum int) 
while @row<[email protected] 
begin 
    Begin Try 
     select @timeid=cast(timeID as decimal(24,0)) from #TestingTable where rownum = @row 
    end try 
    begin catch 
     print cast(@row as varchar(25)) + ' : failed' 
     insert into #fails(rownum) values(@row) 
    end catch 
    set @row = @row+1 
end 
Questions connexes