Wie identifiziere ich die Spalte (n), die für “ verantwortlich sind? String- oder Binärdaten werden abgeschnitten. ”

Ich generiere einige Abfragen automatisch mit Code, den ich aus einer Remote-Pg-Datenbank in SELECT geschrieben und in eine lokale SQL Server-Datenbank eingefügt habe. Einer von ihnen generiert jedoch diesen Fehler:

[Microsoft] [ODBC SQL Server-Treiber] [SQL Server] Zeichenfolge oder Binärdaten werden abgeschnitten. (SQL-22001) [Status war 22001 jetzt 01000]

[Microsoft] [ODBC SQL Server-Treiber] [SQL Server] Die Anweisung wurde beendet. (SQL-01000) in. \ Insert.pl Zeile 106.

Wie finde ich heraus, welche Spalte diesen Fehler erzeugt und die Länge für die fehlt Eingang? Gibt es eine Möglichkeit, dies zu tun, ohne alle varchar zu erraten?

Antwort

Nein, es wird nirgendwo protokolliert. Gehen Sie abstimmen und geben Sie Ihren Business Case an. Dies ist eines der langen Dinge, die in SQL Server behoben werden sollten.

Dies wurde vor Jahren bei Connect angefordert (wahrscheinlich zuerst im SQL Server 2000- oder 2005-Zeitrahmen), dann wieder zum neuen Feedback-System:

Und jetzt wurde es in den folgenden Versionen geliefert:

Im allerersten öffentlichen CTP von SQL Server 2019 wird es nur unter dem Trace-Flag 460 angezeigt. Dies klingt irgendwie geheim, wurde jedoch in dieses Microsoft-Whitepaper . Dies ist in Zukunft das Standardverhalten (kein Ablaufverfolgungsflag erforderlich). Sie können dies jedoch über eine neue Konfiguration mit Datenbankbereich VERBOSE_TRUNCATION_WARNINGS steuern.

Hier ist ein Beispiel:

USE tempdb; GO CREATE TABLE dbo.x(a char(1)); INSERT dbo.x(a) VALUES("foo"); GO 

Ergebnis in allen unterstützten Versionen vor SQL Server 2019:

Nachricht 8152, Ebene 16, Status 30, Zeile 5
Zeichenfolgen- oder Binärdaten werden abgeschnitten.
Die Anweisung wurde beendet.

Jetzt auf SQL Server 2019-CTPs mit aktiviertem Trace-Flag:

DBCC TRACEON(460); GO INSERT dbo.x(a) VALUES("foo"); GO DROP TABLE dbo.x; DBCC TRACEOFF(460); 

Ergebnis zeigt die Tabelle, die Spalte und das ( abgeschnittene , nicht voller ) Wert:

Nachricht 2628, Ebene 16, Status 1, Zeile 11
Zeichenfolgen- oder Binärdaten werden in der Tabelle „tempdb.dbo.x“, Spalte „a“ abgeschnitten. Abgeschnittener Wert: „f“.
Die Anweisung wurde beendet.

Bis Sie zu einer unterstützten Version / CU oder zu einer Azure SQL-Datenbank wechseln können, können Sie Ihre ändern „automagischer“ Code, um die maximale Länge von sys.columns zusammen mit dem Namen, den Sie ohnehin erhalten müssen, abzurufen und dann LEFT(column, max_length) anzuwenden oder was auch immer das Äquivalent von PG ist. Oder, da dies nur bedeutet, dass Sie stillschweigend Daten verlieren, finden Sie heraus, welche Spalten nicht übereinstimmen, und korrigieren Sie die Zielspalten so, dass sie zu allen Daten aus der Quelle passen. Angesichts des Metadatenzugriffs auf beide Systeme und der Tatsache, dass Sie bereits eine Abfrage schreiben, die automatisch mit Quell-> Zielspalten übereinstimmen muss (andernfalls wäre dieser Fehler kaum Ihr größtes Problem), sollten Sie keine Brute-Force-Maßnahmen ergreifen müssen Erraten überhaupt.

Antwort

Wenn Sie Zugriff auf den SQL Server-Import- und Export-Assistenten haben Erstellen Sie in SQL Server Management Studio (Rechtsklick auf Datenbank> Aufgaben> Daten importieren …) eine Aufgabe, die aus SQL Client importiert wird, indem Sie Ihre Abfrage als Datenquelle in die Zieltabelle verwenden.

Bevor Sie den Import ausführen, können Sie die Datenzuordnung überprüfen und erfahren, welche Spalten inkonsistente Feldtypen aufweisen. Wenn Sie die Importaufgabe ausführen, erfahren Sie, welche Spalte (n) nicht importiert werden konnte.

Warnung zur Beispielvalidierung:

Warnung 0x802092a7: Datenfluss Aufgabe 1: Das Einfügen von Daten aus der Datenflussspalte „NARRATIVE“ mit einer Länge von 316 in die Datenbankspalte „NARRATIVE“ mit einer Länge von 60 kann auftreten. (SQL Server-Import- und Export-Assistent)

Antwort

Schließlich Microsoft hat beschlossen, aussagekräftige Informationen für String or binary would be truncated ab SQL Server 2016 SP2 CU, SQL Server 2017 CU12 und in SQL Server 2019 bereitzustellen.

Die Informationen Enthält jetzt sowohl die fehlerhafte Tabellenspalte (vollständig qualifizierter Name) als auch den fehlerhaften Wert (abgeschnitten auf 120 Zeichen):

Nachricht 2628, Ebene 16, Status 1, Zeile x Zeichenfolge oder Binärdaten werden in der Tabelle „TheDb.TheSchema“ abgeschnitten.TheTable „, Spalte“ TheColumn „. Abgeschnittener Wert:“ … „. Die Anweisung wurde beendet.

Antwort

Letztendlich konnte ich keine Möglichkeit finden, die Spalteninformationen abzurufen, ohne sie selbst zu schreiben.

Diese Fehlermeldung wurde von DBD::ODBC Sie können jedoch auch sys.columns (max_length) verwenden (ich weiß nur nicht wie).

Ich habe Code wie diesen über meiner Spaltenliste verwendet, um eine Liste von Arrays mit zwei Elementen abzurufen: COLUMN_NAME und MAX_LENGTH (dokumentiert in DBI column_info() ).

my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ] , map $dbh_mssql->column_info("database", "dbo", $dest_table, $_) , @col_mssql ; 

Dann habe ich die Ausnahmen bei INSERT abgefangen und etwas Nützliches ausgedruckt. In diesem Beispiel sind @$row die Daten, die an sth->execute()

if ($@) { warn "$@\n"; for ( my $idx=0; $idx <= $#{ $row }; $idx++ ) { Dumper { maxlength => $max_lengths[$idx]->[1] , name => $max_lengths[$idx]->[0] , length => length( $row->[$idx] ) , content => $row->[$idx] }; } die; } 
Bitte stimmen Sie auch ab und stimmen Sie der anderen Antwort zu

Kommentare

  • I. ‚ hat keinen Code für sys.columns eingefügt, da ich absolut keine Ahnung hatte, welchen Code Sie derzeit für generiert automatisch “ Ihre Abfragen. ‚ ist wirklich nicht viel komplexer als ich es mir vorstellen könnte, in Ihren Code zu integrieren als SELECT name, object_id, max_length FROM sys.columns;. Da Sie bereits über automatischen Code verfügen, der dies tun muss – oder etwas sehr Ähnliches -, habe ich ‚ nicht gedacht, dass ein Beispiel erforderlich ist.
  • I ‚ Ich bin nicht sicher, wie sys.columns mit zwei Spalten funktioniert, die dieselbe name haben. Außerdem habe ich das Ding mit der Bibliothek anstatt mit sys zum Laufen gebracht. Warum sollte ich das als gewählte Antwort verwenden? Microsoft SQL doesn't have x, do y instead ist ein gültiger Beitrag, aber wenn Ihre y meiner y unterlegen ist, I. ‚ Ich werde etwas anderes tun und es als ausgewählt markieren.
  • Ihre Frage war im Wesentlichen, wie ich herausfinden kann, welche Spalte den Fehler generiert hat (vermutlich , damit Sie diesen einen Punkt beheben können, anstatt die Lösung neu zu konstruieren). Ich habe dir gesagt, wo du suchen sollst: sys.columns. Genau hier sollten Sie nachsehen, um Ihre Quellenspaltenlängen mit den Zielspaltenlängen zu vergleichen. Wie Sie das machen, liegt bei Ihnen. Ich habe ‚ Ihnen nicht gesagt, wie Sie Ihren Code reparieren sollen, da ich absolut keine Ahnung habe, wie Ihre automatische Abfrage überhaupt generiert wurde, und daher, wie gesagt, keine Ahnung hatte, wie um die Längenbestimmungen zu jeder Abfrage hinzuzufügen, die Sie bereits hatten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.