Cum identific coloanele responsabile pentru “ Șirul sau datele binare ar fi trunchiate. ”

Generez câteva interogări automat cu codul pe care l-am scris la SELECT dintr-o bază de date Pg la distanță și le introduc într-o bază de date locală SQL Server. Cu toate acestea, unul dintre ei generează această eroare:

[Microsoft] [ODBC SQL Server Driver] [SQL Server] Șirul sau datele binare ar fi trunchiate. (SQL-22001) [starea era 22001 acum 01000]

[Microsoft] [ODBC SQL Server Driver] [SQL Server] Instrucțiunea a fost terminată. (SQL-01000) at. \ Insert.pl line 106.

Cum aflu ce coloană generează acea eroare și nu are lungimea pentru intrare? Există o modalitate de a face acest lucru fără a ghici forța brută a tuturor varchar?

Răspuns

Nu, nu este înregistrat nicăieri. Mergeți la vot și spuneți cazul dvs. de afaceri; acesta este unul pe lista lungă de lucruri care ar trebui să fie remediate în SQL Server.

Acest lucru a fost solicitat cu ani în urmă pe Connect (probabil mai întâi în intervalul de timp SQL Server 2000 sau 2005), apoi din nou pe noul sistem de feedback:

Și acum a fost livrat în următoarele versiuni:

În primul CTP public al SQL Server 2019, apare doar sub steagul de urmărire 460. Acest lucru pare un secret, dar a fost publicat în această carte albă Microsoft . Acesta va fi comportamentul implicit (nu este necesar niciun semnalizator de urmărire) înainte, deși veți putea controla acest lucru printr-o nouă configurație cu scop de bază de date VERBOSE_TRUNCATION_WARNINGS.

Aici este un exemplu:

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

Rezultă toate versiunile acceptate înainte de SQL Server 2019:

Msg 8152, nivelul 16, starea 30, linia 5 – Șirul sau datele binare ar fi trunchiate.
Declarația a fost terminată.

Acum, pe SQL Server 2019 CTP-uri, cu semnalizatorul de urmărire activat:

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

Rezultatul arată tabelul, coloana și ( trunchiat , nu valoare completă ) valoare:

Msg 2628, nivel 16, Starea 1, Linia 11
Șirul sau datele binare ar fi trunchiate în tabelul „tempdb.dbo.x”, coloana „a”. Valoare trunchiată: „f”.
Declarația a fost încheiată.

Până când puteți trece la o versiune / CU acceptată sau treceți la baza de date SQL Azure, puteți schimba cod „automagic” pentru a trage de fapt max_length din sys.columns, împreună cu numele pe care trebuie să-l obțineți oricum și apoi să aplicați LEFT(column, max_length) sau oricare ar fi echivalentul PG-ului. Sau, deoarece asta înseamnă doar că veți pierde în liniște date, aflați ce coloane sunt nepotrivite și reparați coloanele de destinație astfel încât să se potrivească tuturor datelor de la sursă. Având în vedere accesul la metadate la ambele sisteme și faptul că deja scrieți o interogare care trebuie să se potrivească automat sursei -> coloanelor de destinație (altfel această eroare ar fi cu greu cea mai mare problemă a dvs.), nu ar trebui să faceți nicio ghicind deloc.

Răspuns

Dacă aveți acces pentru a rula Expertul de import și export SQL Server din SQL Server Management Studio (faceți clic dreapta pe baza de date> Activități> Import date …), creați o sarcină care importă din SQL Client utilizând interogarea dvs. ca sursă de date în tabelul de destinație.

Înainte de a rula importul, puteți examina maparea datelor și vă va spune ce coloane au tipuri de câmp inconsistente. Și dacă rulați sarcina de import, vă va spune ce coloane nu au putut fi importate.

Avertisment de validare a eșantionului:

Avertisment 0x802092a7: Fluxul de date Sarcina 1: Trunchierea poate apărea datorită inserării datelor din coloana fluxului de date „NARATIV” cu o lungime de 316 în coloana bazei de date „NARATIVĂ” cu o lungime de 60. (Expertul de import și export SQL Server)

Răspuns

În cele din urmă Microsoft a decis să furnizeze informații semnificative pentru String or binary would be truncated începând cu SQL Server 2016 SP2 CU, SQL Server 2017 CU12 și în SQL Server 2019.

Informațiile acum include atât coloana tabelului contravențional (nume complet calificat), cât și valoarea contravențională (trunchiată la 120 de caractere):

Msg 2628, nivel 16, stat 1, Linia x Șir sau date binare ar fi trunchiate în tabelul „TheDb.TheSchema.TheTable „, coloana” TheColumn „. Valoare trunchiată:” … „. Instrucțiunea a fost terminată.

Răspuns

În cele din urmă, nu am putut găsi o modalitate de a obține informațiile coloanei fără să le scriu eu însumi.

Acest mesaj de eroare a fost generat de DBD::ODBC , totuși puteți folosi sys.columns (max_length) (doar nu știu cum).

Am folosit un cod ca acesta în lista mea de coloane pentru a obține o listă de tablouri cu două elemente, COLUMN_NAME și MAX_LENGTH (documentat în DBI column_info() ).

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

Apoi am prins excepțiile de pe INSERT și am imprimat ceva util. În acest exemplu @$row sunt datele trimise către 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; } 

De asemenea, vă rugăm să votați și să susțineți celălalt răspuns

Comentarii

  • I ‘ nu am pus niciun cod care să facă referire la sys.columns deoarece nu aveam absolut nicio idee ce cod utilizați în prezent pentru a ” generează automat ” interogările dvs. Nu există cu adevărat ‘ mult prea complex pe care l-aș putea ghici despre încorporarea în codul tău decât SELECT name, object_id, max_length FROM sys.columns;. Deoarece aveți deja un cod automagic care trebuie să facă acest lucru – sau ceva asemănător – nu credeam că ‘ nu credeam că este necesar un exemplu.
  • Eu ‘ Nu sunt sigur cum funcționează sys.columns cu două coloane care au același name. De asemenea, am reușit să funcționeze folosind biblioteca mai degrabă decât sys, de ce aș face asta ca răspuns ales? Microsoft SQL doesn't have x, do y instead este o contribuție validă, dar dacă y este inferior y al meu, ‘ voi face ceva diferit și îl voi marca ca ales.
  • Întrebarea dvs. a fost, în esență, cum pot afla ce coloană a generat eroarea (probabil , astfel încât ați putea remedia acel loc, în loc să re-proiectați soluția). Ți-am spus unde să cauți: sys.columns. Care este exact locul în care ar trebui să căutați pentru a compara lungimile coloanei sursă cu lungimile coloanei de destinație. Depinde de tine cum faci asta. Nu ți-am spus ‘ că nu îți spun cum să îți remediez codul, pentru că nu am absolut nicio idee despre cum a fost generată interogarea automagică, așa că, așa cum am spus, nu știam cum pentru a adăuga determinările de lungime la orice interogare pe care ați avut-o deja.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *