2009-07-07 6 views
5

SQL Server 2005 Frage:SQL Server: Finden Sie heraus, welche Zeile die TSQL verursacht scheitern (SSIS)

Ich bin auf einem Datenkonvertierung Projekt arbeiten, wo ich 80k + Reihen nehme und sie von einem Tisch bewegt zu Ein weiterer. Wenn ich den TSQL laufe, bombardiert er mit verschiedenen Fehlern, die mit dem Umwandeln von Typen oder was auch immer zu tun haben. Gibt es eine Möglichkeit herauszufinden, welche Zeile den Fehler verursacht hat?

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

UPDATE:

Ich bin eine INSERT INTO TABLE1 Durchführung (...) SELECT. .. FROM TABLE2 Table2 ist nur ein paar Varchar-Felder, in denen TABLE1 die richtigen Typen hat.

Dieses Skript wird in einen Sproc geschrieben und von einem SSIS-Paket ausgeführt. Das SSIS-Paket importiert zuerst 5 große flache Dateien in TABLE2.

Hier ist eine Beispielfehlermeldung: "Die Konvertierung eines Char-Datentyps in einen Datetime-Datentyp führte zu einem out-of-Range-Datetime-Wert."

Es gibt viele Datumsfelder. In TABELLE2 gibt es Datenwerte wie '02/05/1075 'für Geburtsdatum. Ich möchte jede Zeile untersuchen, die den Fehler verursacht, sodass ich der für die fehlerhaften Daten zuständigen Abteilung Bericht erstatten kann, damit sie sie korrigieren kann.

+0

Können Sie uns einige Beispiele für den Fehler geben? Wie verschieben Sie Daten mit einer insert-Anweisung oder einem Cursor? Nach meinem Wissen gibt es wirklich keine Protokolldatei, die Ihnen genau sagen wird, was der Fehler ist, aber vielleicht mit einigen Fehlermeldungen können wir Sie in die richtige Richtung weisen. – OhioDude

+0

Bitte achten Sie mehr auf Ihre Tag-Auswahl. –

+1

Wenn es um Casting geht, gibt es ISNUMERIC- und ISDATE-Funktionen, um zu testen, ob eine Zeichenfolge erfolgreich implizit auf eine Zahl oder ein Datum umgesetzt werden kann. ISNUMERIC hat jedoch nach meiner Erfahrung einen Makel bezüglich Kommas und Leerzeichen. Aber ja, Ihr OP sollte viel genauer sein bezüglich der Fehler, denen Sie begegnen. –

Antwort

3

Was ich tue, ist das Rowset in der Hälfte mit einer WHERE-Klausel aufgeteilt:

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

und dann halten die Werte auf dem zwischen einem Teil der Klausel, wo zu ändern. Ich habe das oft von Hand gemacht, aber mir fällt ein, dass Sie das Teilen mit ein wenig .Net-Code in einer Schleife automatisieren, Ausnahmen abfangen und dann auf die Zeile reduzieren können, die die Ausnahme nach und nach wirft.

+4

Falsche Syntax und schlechte Idee, um das Problem zu lösen. Es wird funktionieren (sobald der Syntaxfehler behoben ist), aber es ist am wenigsten effizient und muss wirklich manuell ausgeführt werden, anstatt in einem Paket zu laufen. Schlechte Daten sind mit der Funktion isdate() leicht zu identifizieren. – HLGEM

+0

Das fehlerhafte SQL wurde behoben. –

0

Wenn Sie mit Cursors arbeiten, ja und ist trivial. Wenn Sie nicht mit Cursorn arbeiten, glaube ich nicht, weil SQL-Operationen ACID oder Transaktionen an sich sind.

2

Ich nehme an, Sie tun das Update mit der INSERT INTO ...

Stattdessen versuchen, das Update mit dem Cursor zu tun, Handhabung Verwendung Ausnahme, den Fehler zu fangen und alle melden Sie brauchen: die Zeilennummer es versäumt auf usw.

+2

stimme zu 80k rows ist nicht so viele wirklich, so Cursor wird dort ankommen; Wenn es mehr als einen Fehler gibt, hilft das. Vergessen Sie nicht, dass Sie in SQL 2005 versuchen/fangen können, so dass Sie die Zeilen speichern können, die fehlgeschlagen sind, und weitermachen mit denen, die funktionierten. – u07ch

+1

good point, u07ch: füge alle ein, die keinen Fehler ausgegeben haben, dann kannst du einfach JOIN ... WHERE RIGHT.X NULL verlassen, um diejenigen zu überprüfen, die nicht alle in einer Anweisung eingefügt wurden. Wenn es viele Zeilen gibt, die fehlschlagen, wäre dies die beste Lösung, anstatt 1K fehlerhafte Zeilen aus 80K zu reparieren. Aber es ist wahrscheinlich genug, um 1-2 verschiedene Ursachen zu finden, die anderen sollten gleich sein und sollten leicht zu beheben sein. – van

1

Wenn Sie Schleifen verwenden, fügen Sie Drucke in die Schleife ein.

Wenn Sie menügeführte Operationen verwenden, fügen Sie eine restriktive WHERE-Bedingung hinzu und führen Sie sie aus. Führen Sie es weiter aus (jedes Mal, wenn es immer restriktiver wird), bis Sie die Zeile in den Daten finden. Wenn Sie es für Blöcke von N Zeilen ausführen könnten, dann wählen Sie diese Zeilen aus und sehen Sie sich diese an.

ADD CASE-Anweisungen, die Probleme zu fangen (Umwandlung, dass schlechter Wert auf NULL oder whetever) und setzen einen Wert in einem neuen FlagColumn Ihnen die Art des Problems zu sagen:

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 

dann die neuen konvertierten Daten wählen aus wo FlagColumn IS NOT NULL

Sie select-Anweisungen mit IsNumeric() oder isdate() Funktionen auf den verschiedenen Spalten der Quelldaten unter Verwendung versuchen könnte

EDIT

Es gibt viele Datumsfelder. In TABELLE2, gibt es Datenwerte wie '02/05/1075 'für Geburtsdatum. Ich möchte untersuchen jede Zeile, die den Fehler verursacht, so kann ich an die Abteilung melden, die für die schlechten Daten verantwortlich ist, damit sie es korrigieren können.

verwenden alle schlechten Datum Zeilen zurückgeben:

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

Dies ist nicht der Weg, um es mit SSIS zu tun ist. Sie sollten den Datenfluss von Ihrer Quelle zu Ihrem Ziel mit den Transformationen haben, die Sie in der Mitte benötigen. Sie können Fehlerdetails und tatsächlich Fehlerzeilen erhalten, indem Sie die Fehlerausgabe des Ziels verwenden.

Ich sende oft die Fehlerausgabe eines Ziels an ein anderes Ziel - eine Textdatei oder eine Tabelle, die eingerichtet wurde, um alles zuzulassen, einschließlich Daten, die im realen Ziel nicht gültig gewesen wären.

Eigentlich, wenn Sie das Standardverfahren in SSIS tun, dann sollten Datentypabweichungen zur Entwurfszeit erkannt werden.

0

John Sauders hat die richtige Idee, es gibt bessere Möglichkeiten, diese Art der Verarbeitung mit SSIS zu machen. Allerdings ist es derzeit keine Option, SSIS zu lernen und das Paket neu zu erstellen, um den Prozess vollständig zu ändern. Daher biete ich diesen Rat an. Sie scheinen Probleme mit den Daten zu haben, die falsch sind. Führen Sie also zuerst eine Abfrage aus, um die fehlerhaften Datensätze zu identifizieren und sie in eine Ausnahmetabelle einzufügen. Dann fügen Sie nur die verbleibenden Datensätze ein. Etwas wie:

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 

Dann natürlich können Sie den Inhalt der Ausnahmetabelle an die Menschen senden, der die schlechten Daten.

+0

Er sagte, er habe bereits SSIS verwendet, und Source -> Dest -> Fehler ist nicht sehr schwer ... –

+0

Ich stimme zu, so würde ich es tun, aber SSIS ist nicht einfach zu lernen, wie man richtig und er verwendet kann unter Zeitdruck stehen. Ich weiß, dass ich seit Jahren DTS-Pakete mache, aber diese Methode wäre mir nie in den Sinn gekommen, hätte ich kein formelles SSIS-Training gehabt. Er verwendet eindeutig t-sql-Skripts, nicht den Datenfluss, daher ist ihm möglicherweise völlig unbekannt, wie der Datenfluss zu verwenden ist. Es ist nicht einfach beim ersten Mal. – HLGEM

+0

Sie wissen, es ist mir nie in den Sinn gekommen, dass er SSIS verwenden könnte und _nicht_ einen Datenfluss verwenden würde. –

2

Nicht gerade ein Cursor, aber so effektiv - ich hatte über 4 Millionen Zeilen mit mehreren Conversion-Fehlern zu untersuchen. Hier ist, was ich verwendet habe, und es führte zu einer zwei temporäre Tabellen eins mit all meinen Werten und zugewiesenen Zeilen und einem, das einfach eine Liste von Zeilen in der ersten temporären Tabelle enthielt, die nicht konvertiert werden konnte.

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 
Verwandte Themen