SQL Server Insert Into - So identifizieren Sie die Spalte, die einen Kürzungsfehler verursacht

11

Ich habe eine gespeicherte Prozedur, die 650 Felder in eine Tabelle einfügt. Das Einfügen schlägt mit einem Kürzungsfehler fehl.

Es ist einfach

INSERT INTO
SELECT (a bunch of fields) 
FROM (a bunch of tables)

Unten ist die Fehlermeldung:

Nachricht 8152, Ebene 16, Status 14, Prozedur DSP_Procedure, Zeile 1075 Zeichenfolge oder Binärdaten werden abgeschnitten.

Gibt es eine schnelle Möglichkeit, um festzustellen, welches Feld den Kürzungsfehler verursacht?

Die Tatsache, dass die in die Tabelle einzufügende select-Anweisung 650 Felder enthält, macht es schwierig, genau zu bestimmen, welches Feld den Kürzungsfehler verursacht.

Ich denke, ich kann vielleicht Feldblöcke gleichzeitig auskommentieren, damit der SP jeweils nur 100 Felder einfügt und dann den SP 6 oder 7 verschiedene Male ausführt, bis ich mich zumindest auf eine Gruppe von 100 Feldern eingrenzen kann Das enthält das Feld, das den Kürzungsfehler verursacht.

Alternativ denke ich, dass ich vielleicht nur SELECT INTOeine neue Tabelle erstellen und dann die Datenlängen in der Tabelle mit den Datenlängen der Zieltabelle vergleichen kann, in die ich in meinen SP einfügen möchte, um festzustellen, welches Feld eine längere als erwartete Feldlänge enthält. ..

Ich verwende SQL Server 2014.

Irgendwelche einfacheren Alternativen?

Juan Velez
quelle
1
Ich würde zu INFORMATION_SCHEMA.COLUMNS gehen und die Datentypen mit denen vergleichen, die Sie einfügen möchten. Leider verfügt SQL Server nicht über dynamische Datentypen für die Variablendeklaration wie ORACLE.
MguerraTorres
2
Ich würde Ihre zweite Option verwenden, in eine neue Tabelle (oder #temp) einfügen und dann die Spaltenlängen vergleichen. Oder Sie können LEN () um alle Spalten in der Auswahl wickeln und dann von einer Außenabfrage eine MAX () für jede Spalte ausführen lassen, die Ihnen die größte Textlänge für die Felder ergibt. Dies setzt natürlich voraus, dass es sich um ein Zeichenfeld handelt, das Ihnen Probleme bereitet. Verwenden Sie nicht smalldatetime oder tinyint?
Jonathan Fite
1
Ich würde mich für den "Select Into" -Ansatz entscheiden und die Spaltenlängen vergleichen, ja. Möglicherweise mit "WHERE 1 = 0", damit die Tabelle keine Zeilen enthält. Umständlich, wenn Ihr SELECT keine eindeutigen Namen für ausgewählte Spalten enthält. Ich formatiere lange Spaltenlisten als eine Skriptzeile pro Spalte, dann bei Bedarf den Spaltennamen "AS" in der nächsten Zeile und nach vier Spalten eine leere Zeile, um das Platzieren in der Liste zu erleichtern. Dies unterstützt auch das Auswählen vieler Zeilen und das Ausführen von Strg + K Strg + C, um sie in Kommentare zu ändern, sodass Sie den Einfügevorgang auf diese Weise angreifen können, die ausgelassenen Spalten jedoch nullwertfähig sein müssen.
Robert Carnegie

Antworten:

9

Leider sind Sie auf ein ziemlich altes "Feature" gestoßen . Seit 2008 ist ein Connect-Ticket geöffnet, und seit fast zehn Jahren ist dies nicht mehr signifikant genug, um eine Korrektur zu rechtfertigen.

Die Standardumgehung besteht, wie Sie sich vorgestellt haben, darin select into..., Tabellenmetadaten zu vergleichen. Eine andere Möglichkeit ist die binäre Suche in der betreffenden Spalte, aber das ist auch manuelle Arbeit. Es gibt einige Hacks für den Metadatenvergleich, aber eine einfache, elegante Lösung gibt es nicht. Vielleicht wären einige Tools von Drittanbietern hilfreich, aber mir sind solche nicht bekannt.

vonPryz
quelle
1

Die Verwendung von (QUERYTRACEON 460) hat bei mir am Ende meiner Abfrage nicht funktioniert.

Ich habe es auf DB-Ebene eingeschaltet und es hat funktioniert:

DBCC TRACEON(460, -1);
GO

Schalten Sie es jedoch wieder aus, sobald Sie das Problem gefunden und behoben haben. Lassen Sie es nicht eingeschaltet!

DBCC TRACEOFF(460, -1);
GO
Taylor Brown
quelle