Jak identifikuji sloupce odpovědné za “ Řetězcová nebo binární data by byla zkrácena. ”

Generuji automaticky některé dotazy pomocí kódu, který jsem napsal do SELECT ze vzdálené databáze Pg, a vložím jej do místní databáze serveru SQL. Jeden z nich však generuje tuto chybu:

[Microsoft] [Ovladač serveru ODBC SQL] [SQL Server] Řetězec nebo binární data by byla zkrácena. (SQL-22001) [stav byl 22001 nyní 01000]

[Microsoft] [ovladač ODBC SQL Server] [SQL Server] Příkaz byl ukončen. (SQL-01000) at. \ Insert.pl line 106.

Jak zjistím, který sloupec generuje tuto chybu a postrádá délku vstup? Existuje způsob, jak to udělat bez hádání hrubou silou všech varchar?

Odpovědět

Ne, není to nikde přihlášeno. Hlasujte a uveďte svůj obchodní případ; toto je jeden z dlouhého seznamu věcí, které by měly být opraveny na serveru SQL Server.

Toto bylo požadováno před lety na serveru Connect (pravděpodobně nejprve v časovém rámci serveru SQL Server 2000 nebo 2005), pak znovu v novém systému zpětné vazby:

A nyní byl dodán v následujících verzích:

V úplně prvním veřejném CTP serveru SQL Server 2019 se zobrazuje pouze pod příznakem trasování 460. To zní trochu tajně, ale bylo publikováno v tento dokument Microsoftu . Toto bude výchozí chování (není vyžadován žádný příznak trasování), i když to budete moci ovládat pomocí nové konfigurace s rozsahem databáze VERBOSE_TRUNCATION_WARNINGS.

Zde je příklad:

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

Výsledek ve všech podporovaných verzích před SQL Server 2019:

Zpráva 8152, úroveň 16, stav 30, řádek 5
Řetězcová nebo binární data by byla zkrácena.
Prohlášení bylo ukončeno.

Nyní na CTP serveru SQL Server 2019 se zapnutým příznakem trasování:

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

Výsledek zobrazuje tabulku, sloupec a ( zkrácený , ne plná ) hodnota:

Zpráva 2628, úroveň 16, stát 1, řádek 11
Řetězcová nebo binární data by byla zkrácena v tabulce „tempdb.dbo.x“, sloupec „a“. Zkrácená hodnota: „f“.
Výkaz byl ukončen.

Dokud se nepohnete na podporovanou verzi / CU nebo na Azure SQL Database, můžete změnit „automagic“ kód, který ve skutečnosti vytáhne max_length z sys.columns, spolu se jménem, které tam stejně musíte dostat, a poté použije LEFT(column, max_length) nebo jakýkoli ekvivalent PG. Nebo to prostě znamená, že tiše ztratíte data, jděte na to, které sloupce se neshodují, a opravte cílové sloupce tak, aby se vešly na všechna data ze zdroje. Vzhledem k přístupu metadat k oběma systémům a skutečnosti, že „již píšete dotaz, který musí automaticky odpovídat sloupcům zdroj -> cíl (jinak by tato chyba byla jen stěží vaším největším problémem), byste neměli dělat žádnou hrubou sílu hádám vůbec.

Odpovědět

Pokud máte přístup ke spuštění Průvodce importem a exportem serveru SQL z SQL Server Management Studio (klepněte pravým tlačítkem myši na databázi> Úkoly> Importovat data …), vytvořte úkol, který importuje z klienta SQL pomocí vašeho dotazu jako zdroje dat do cílové tabulky.

Před spuštěním importu můžete zkontrolovat mapování dat a zjistit, které sloupce mají nekonzistentní typy polí. A pokud spustíte úlohu importu, řekne vám, které sloupce se nepodařilo importovat.

Upozornění na ověření vzorku:

Varování 0x802092a7: Úloha datového toku 1: Může dojít ke zkrácení kvůli vložení dat ze sloupce toku dat „NARRATIVE“ s délkou 316 do sloupce databáze „NARRATIVE“ s délkou 60. (Průvodce importem a exportem serveru SQL Server)

Odpověď

Nakonec Microsoft se rozhodl poskytnout smysluplné informace pro String or binary would be truncated počínaje SQL Server 2016 SP2 CU, SQL Server 2017 CU12 a SQL Server 2019.

Informace nyní zahrnuje jak sloupec tabulky přestupků (plně kvalifikovaný název), tak i hodnotu přestupku (zkrácen na 120 znaků):

Zpráva 2628, úroveň 16, stav 1, Řádek x Řetězec nebo binární data by byla zkrácena v tabulce „TheDb.TheSchema.TheTable „, sloupec“ TheColumn „. Zkrácená hodnota:“ … „. Výkaz byl ukončen.

Odpovědět

Nakonec jsem nemohl najít způsob, jak získat informace o sloupci, aniž bych je sám napsal.

Tato chybová zpráva byla vygenerována DBD::ODBC , můžete však také použít sys.columns (max_length) (jen nevím jak).

Použil jsem takový kód na seznam sloupců, abych získal seznam polí se dvěma prvky, COLUMN_NAME a MAX_LENGTH (dokumentováno v DBI column_info() ).

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

Potom jsem zachytil výjimky na INSERT a vytiskl něco užitečného. V tomto příkladu @$row jsou data odeslaná 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; } 

Rovněž prosím hlasujte a hlasujte pro druhou odpověď

Komentáře

  • I neudělal ‚ žádný kód odkazující na sys.columns, protože jsem vůbec netušil, jaký kód aktuálně používáte pro “ automaticky “ generujte své dotazy. Opravdu není ‚ příliš složitější, než bych mohl odhadnout o začlenění do vašeho kódu, než SELECT name, object_id, max_length FROM sys.columns;. Jelikož již máte automatický kód, který to musí dělat – nebo něco podobného -, nemyslel jsem si ‚ že je nutný příklad.
  • Já ‚ si nejsem jistý, jak sys.columns pracuje se dvěma sloupci, které mají stejné name. Také jsem dostal věc pracovat pomocí knihovny, spíše než sys, proč bych to udělal jako zvolenou odpověď? Microsoft SQL doesn't have x, do y instead je platný příspěvek, ale pokud je váš y horší než můj y, ‚ udělám něco jiného a označím to jako zvolené.
  • Vaše otázka byla v podstatě tak, jak zjistím, který sloupec generoval chybu (pravděpodobně , takže byste mohli opravit toto jedno místo, místo toho, abyste přepracovali řešení). Řekl jsem ti, kde hledat: sys.columns. Což je přesně tam, kde byste měli hledat, abyste porovnali délky zdrojových sloupců s délkami cílových sloupců. Jak to uděláte, je jen na vás. Neřekl jsem vám ‚ jak opravit váš kód, protože vůbec netuším, jak se váš automatický dotaz generuje, takže, jak jsem řekl, jsem neměl tušení, jak přidat určení délky k jakémukoli dotazu, který jste již měli.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *