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ěď
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.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ůjy
, ‚ udělám něco jiného a označím to jako zvolené.