Wie identifiziere ich die Spalte (n), die für "Zeichenfolge oder Binärdaten werden abgeschnitten" verantwortlich sind?

31

Ich generiere einige Abfragen automatisch mit Code, den ich aus einer entfernten 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) [Stand war 22001 jetzt 01000]

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

Wie finde ich heraus, welche Spalte diesen Fehler generiert und die Länge für die Eingabe fehlt? Gibt es eine Möglichkeit, dies zu tun, ohne die ganze Zeit brutal zu raten varchar?

Evan Carroll
quelle

Antworten:

35

Nein, es wird nirgendwo protokolliert. Wählen Sie und geben Sie Ihren Geschäftsgrundsatz an. Dies ist eine in der langen Liste der Dinge, die in SQL Server behoben werden sollten.

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

Und jetzt wurde es in SQL Server 2019 , SQL Server 2017 CU12, ausgeliefert und wird in einer zukünftigen SQL Server 2016 SP2-CU angezeigt.

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

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:

Meldung 8152, Ebene 16, Status 30, Zeile 5
Zeichenfolge oder Binärdaten werden abgeschnitten.
Die Anweisung wurde beendet.

Jetzt auf SQL Server 2019-CTPs mit aktiviertem Ablaufverfolgungsflag:

DBCC TRACEON(460);
GO

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

Das Ergebnis zeigt die Tabelle, die Spalte und den Wert ( abgeschnitten , nicht voll ):

Meldung 2628, Ebene 16,
Status 1, Zeile 11 Zeichenfolge oder Binärdaten werden in Tabelle 'tempdb.dbo.x', Spalte 'a' abgeschnitten. Verkürzter Wert: 'f'.
Die Anweisung wurde beendet.

Bis Sie alles löschen und auf SQL Server 2019 aktualisieren oder auf Azure SQL-Datenbank umsteigen können, können Sie Ihren "automagic" -Code so ändern, dass er die max_length sys.columnszusammen mit dem Namen, den Sie ohnehin erhalten müssen, abruft und dann LEFT(column, max_length)oder anwendet was auch immer PGs Äquivalent ist. Oder, da dies nur bedeutet, dass Sie stillschweigend Daten verlieren, ermitteln Sie, 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 den Quell-> Zielspalten übereinstimmen muss (andernfalls wäre dieser Fehler kaum Ihr größtes Problem), sollten Sie keine grobe Gewalt anwenden müssen überhaupt erraten.

Aaron Bertrand
quelle
2

Wenn Sie über die Berechtigung verfügen, den SQL Server-Import- und -Export-Assistenten in SQL Server Management Studio auszuführen (klicken Sie mit der rechten Maustaste auf Datenbank> Aufgaben> Daten importieren ...), erstellen Sie eine Aufgabe, die mit Ihrer Abfrage aus SQL Client als Datenquelle in das Ziel importiert wird Tabelle.

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, werden Sie darüber informiert, welche Spalte (n) nicht importiert werden konnten.

Beispielvalidierungswarnung:

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 zu einer Kürzung führen. (SQL Server-Import- und -Export-Assistent)

bubbassauro
quelle
1

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

Diese Fehlermeldung wurde von generiert DBD::ODBC, kann man aber auch verwenden sys.columns (max_length)(ich weiß nur nicht wie).

Ich habe Code wie diesen über meiner Spaltenliste verwendet, um eine Liste von Arrays mit zwei Elementen zu erhalten, dem COLUMN_NAMEund MAX_LENGTH(in DBIcolumn_info() dokumentiert ).

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

Dann erkannte ich die Ausnahmen INSERTund druckte etwas Nützliches aus. In diesem Beispiel @$rowwerden die Daten an gesendetsth->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

Evan Carroll
quelle
2
Ich habe keine Code-Referenzierung angegeben, sys.columnsda ich absolut keine Ahnung hatte, welchen Code Sie derzeit verwenden, um Ihre Abfragen "automatisch" zu generieren. Es gibt wirklich nicht viel komplexer, als ich es mir vorstellen könnte SELECT name, object_id, max_length FROM sys.columns;. Da Sie bereits automagischen Code haben, der dies tun muss - oder so ähnlich -, habe ich nicht gedacht, dass ein Beispiel notwendig ist.
Aaron Bertrand
Ich bin mir nicht sicher, wie sys.columnsdas mit zwei Spalten funktioniert, die das gleiche haben name. Außerdem habe ich das Ding über die Bibliothek zum Laufen gebracht, anstatt syswarum sollte ich das als die gewählte Antwort machen? Microsoft SQL doesn't have x, do y insteadist ein gültiger Beitrag, aber wenn Ihr ymeinem unterlegen ist, werde yich etwas anderes tun und es als ausgewählt markieren.
Evan Carroll
1
Ihre Frage lautete im Wesentlichen: Wie finde ich heraus, welche Spalte den Fehler verursacht hat? Ich habe dir gesagt, wo du suchen sollst: sys.columns. Genau hier sollten Sie Ihre Quellspaltenlängen mit den Zielspaltenlängen vergleichen. Wie Sie das machen, liegt ganz bei Ihnen. Ich habe Ihnen nicht gesagt, wie Sie Ihren Code reparieren sollen, weil ich überhaupt keine Ahnung habe, wie Ihre automagische Abfrage generiert wurde, und daher, wie ich bereits sagte, keine Ahnung hatte, wie Sie die Längenbestimmungen zu der bereits vorhandenen Abfrage hinzufügen können .
Aaron Bertrand
1

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

Die Informationen enthalten jetzt sowohl die Spalte der beleidigenden Tabelle (vollqualifizierter Name) als auch den beleidigenden Wert (abgeschnitten auf 120 Zeichen):

Meldung 2628, Ebene 16, Status 1, Zeile x Zeichenfolge oder Binärdaten werden in Tabelle 'TheDb.TheSchema.TheTable', Spalte 'TheColumn' abgeschnitten. Verkürzter Wert: '...'. Die Anweisung wurde beendet.

Alexei
quelle