Niektóre zapytania generuję automagicznie za pomocą kodu, który napisałem do SELECT ze zdalnej bazy danych Pg i wstawiam je do lokalnej bazy danych SQL Server. Jednak jeden z nich generuje ten błąd:
[Microsoft] [ODBC SQL Server Driver] [SQL Server] Ciąg lub dane binarne zostałyby obcięte. (SQL-22001) [stan to 22001, teraz 01000]
[Microsoft] [Sterownik ODBC SQL Server] [SQL Server] Instrukcja została zakończona. (SQL-01000) pod adresem. \ Insert.pl line 106.
Jak sprawdzić, która kolumna generuje ten błąd i nie zawiera długości Wejście? Czy można to zrobić bez brutalnego zgadywania wszystkich varchar
?
Odpowiedź
Nie, nie jest nigdzie rejestrowany. Idź głosować i przedstaw swoje uzasadnienie biznesowe; jest to jedna z długiej listy rzeczy, które powinny zostać naprawione w SQL Server.
Poproszono o to lata temu w Connect (prawdopodobnie najpierw w ramach czasowych SQL Server 2000 lub 2005), a potem znowu w nowym systemie opinii:
A teraz został dostarczony w następujących wersjach:
W pierwszym publicznym CTP SQL Server 2019 pojawia się tylko pod flagą śledzenia 460. Brzmi to trochę tajemniczo, ale zostało opublikowane w ten oficjalny dokument firmy Microsoft . Będzie to domyślne zachowanie (nie jest wymagana flaga śledzenia) w przyszłości, chociaż będzie można to kontrolować za pomocą nowej konfiguracji zakresu bazy danych VERBOSE_TRUNCATION_WARNINGS
.
Tutaj to przykład:
USE tempdb; GO CREATE TABLE dbo.x(a char(1)); INSERT dbo.x(a) VALUES("foo"); GO
Wynik we wszystkich obsługiwanych wersjach starszych niż SQL Server 2019:
Msg 8152, poziom 16, stan 30, wiersz 5
Dane ciągowe lub binarne zostałyby obcięte.
Instrukcja została zakończona.
Teraz na serwerach CTP programu SQL Server 2019, z włączoną flagą śledzenia:
DBCC TRACEON(460); GO INSERT dbo.x(a) VALUES("foo"); GO DROP TABLE dbo.x; DBCC TRACEOFF(460);
Wynik pokazuje tabelę, kolumnę i ( obcięte , a nie pełna ) wartość:
Msg 2628, poziom 16, Stan 1, Wiersz 11
Ciąg lub dane binarne zostałyby obcięte w tabeli „tempdb.dbo.x”, w kolumnie „a”. Obcięta wartość: „f”.
Instrukcja została zakończona.
Dopóki nie będzie można przejść do obsługiwanej wersji / CU lub do Azure SQL Database, można zmienić Kod „automagic”, aby faktycznie pobrać max_length z sys.columns
, wraz z nazwą, którą i tak musisz tam dostać, a następnie zastosować LEFT(column, max_length)
lub jakikolwiek odpowiednik PG jest. Lub, ponieważ oznacza to po prostu, że po cichu stracisz dane, dowiedz się, które kolumny są niedopasowane i napraw kolumny docelowe, aby pasowały do wszystkich danych ze źródła. Biorąc pod uwagę dostęp metadanych do obu systemów i fakt, że już piszesz zapytanie, które musi automagicznie pasować do kolumn źródłowych -> docelowych (w przeciwnym razie ten błąd nie byłby największym problemem), nie powinieneś wykonywać żadnej brutalnej siły zgadywanie w ogóle.
Odpowiedź
Jeśli masz dostęp do uruchomienia Kreatora importu i eksportu SQL Server z SQL Server Management Studio (baza danych kliknij prawym przyciskiem myszy> Zadania> Importuj dane …), utwórz zadanie, które importuje dane z klienta SQL, używając zapytania jako źródła danych do tabeli docelowej.
Przed rozpoczęciem importu możesz przejrzeć mapowanie danych i powie Ci, które kolumny mają niespójne typy pól. A jeśli uruchomisz zadanie importu, powie Ci, których kolumn nie udało się zaimportować.
Przykładowe ostrzeżenie o walidacji:
Ostrzeżenie 0x802092a7: Zadanie przepływu danych 1: Może wystąpić obcięcie z powodu wstawienia danych z kolumny przepływu danych „NARRATIVE” o długości 316 do kolumny bazy danych „NARRATIVE” o długości 60. (Kreator importu i eksportu SQL Server)
Odpowiedź
Wreszcie Microsoft postanowił dostarczyć znaczące informacje dla String or binary would be truncated
, począwszy od SQL Server 2016 SP2 CU, SQL Server 2017 CU12 i SQL Server 2019.
Informacje zawiera teraz zarówno kolumnę tabeli naruszającej zasady (w pełni kwalifikowana nazwa), jak i nieprawidłową wartość (obciętą do 120 znaków):
Msg 2628, poziom 16, stan 1, Linia x Ciąg lub dane binarne zostałyby obcięte w tabeli „TheDb.Schema.TheTable ”, kolumna„ TheColumn ”. Obcięta wartość:„ … ”. Instrukcja została zakończona.
Odpowiedź
Ostatecznie nie mogłem znaleźć sposobu na uzyskanie informacji o kolumnie bez ich samodzielnego pisania.
Ten komunikat o błędzie został wygenerowany przez DBD::ODBC
, możesz też użyć sys.columns (max_length)
(po prostu nie wiem jak).
Użyłem takiego kodu na mojej liście kolumn, aby uzyskać listę tablic z dwoma elementami: COLUMN_NAME
i MAX_LENGTH
(udokumentowane w DBI column_info()
).
my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ] , map $dbh_mssql->column_info("database", "dbo", $dest_table, $_) , @col_mssql ;
Następnie złapałem wyjątki na INSERT
i wydrukowałem coś pożytecznego. W tym przykładzie @$row
to dane wysłane do 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; }
Zagłosuj również i zagłosuj za drugą odpowiedzią
sys.columns
, ponieważ nie miałem absolutnie pojęcia, jakiego kodu obecnie używasz do ” automagicznie ” generuj zapytania. Naprawdę nie ' nie jest zbyt skomplikowane, jakbym mógł się domyślić, jeśli chodzi o włączenie do kodu niżSELECT name, object_id, max_length FROM sys.columns;
. Ponieważ masz już kod automagiczny, który musi to robić – lub coś bardzo podobnego – nie ' myślę, że przykład był potrzebny.sys.columns
działa z dwiema kolumnami, które mają takie samename
. Co więcej, działało przy użyciu biblioteki, a niesys
, dlaczego miałbym to wybrać jako wybraną odpowiedź?Microsoft SQL doesn't have x, do y instead
to ważny wkład, ale jeśli Twójy
jest gorszy od mojegoy
, ja ' mam zamiar zrobić coś innego i oznaczyć to jako wybrane.