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; }
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 alsSELECT 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 dieselbename
haben. Außerdem habe ich das Ding mit der Bibliothek anstatt mitsys
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 Ihrey
meinery
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.