Ik genereer automatisch een aantal queries met code die ik naar SELECT heb geschreven vanuit een externe Pg-database, en die ik in een lokale SQL Server-database heb ingevoegd. Een van hen genereert echter deze fout:
[Microsoft] [ODBC SQL Server-stuurprogramma] [SQL Server] String- of binaire gegevens worden afgekapt. (SQL-22001) [status was 22001 nu 01000]
[Microsoft] [ODBC SQL Server-stuurprogramma] [SQL Server] De instructie is beëindigd. (SQL-01000) op. \ Insert.pl regel 106.
Hoe kom ik erachter welke kolom die fout genereert en niet de lengte heeft voor de invoer? Is er een manier om dit te doen zonder alle varchar
te raden?
Antwoord
Nee, het is nergens gelogd. Ga stemmen en noem uw business case; dit is er een op de lange lijst met dingen die moeten worden opgelost in SQL Server.
Dit werd jaren geleden aangevraagd op Connect (waarschijnlijk eerst in het SQL Server 2000 of 2005-tijdsbestek), en dan weer op het nieuwe feedbacksysteem:
En nu is het geleverd in de volgende versies:
In de allereerste openbare CTP van SQL Server 2019 verschijnt het alleen onder traceringsvlag 460. Dit klinkt een beetje geheim, maar het is gepubliceerd in deze Microsoft-whitepaper . Dit zal het standaardgedrag zijn (geen traceringsvlag vereist) in de toekomst, hoewel u dit kunt regelen via een nieuwe configuratie met databasebereik VERBOSE_TRUNCATION_WARNINGS
.
Hier is een voorbeeld:
USE tempdb; GO CREATE TABLE dbo.x(a char(1)); INSERT dbo.x(a) VALUES("foo"); GO
Resultaat in alle ondersteunde versies voorafgaand aan SQL Server 2019:
Msg 8152, niveau 16, staat 30, regel 5
String- of binaire gegevens worden afgekapt.
De instructie is beëindigd.
Nu, op SQL Server 2019 CTPs, met de traceringsvlag ingeschakeld:
DBCC TRACEON(460); GO INSERT dbo.x(a) VALUES("foo"); GO DROP TABLE dbo.x; DBCC TRACEOFF(460);
Resultaat toont de tabel, de kolom en de ( afgekapt , niet volledige ) waarde:
Msg 2628, niveau 16, State 1, Line 11
String- of binaire gegevens worden afgekapt in tabel “tempdb.dbo.x”, kolom “a”. Afgekapte waarde: “f”.
De instructie is beëindigd.
Totdat u naar een ondersteunde versie / CU kunt gaan, of naar Azure SQL Database, kunt u uw “automagic” -code om daadwerkelijk de max_length uit sys.columns
te halen, samen met de naam die u daar toch moet krijgen, en vervolgens LEFT(column, max_length)
toe te passen of wat het equivalent van PG ook is. Of, aangezien dat gewoon betekent dat je stilletjes gegevens verliest, ga uitzoeken welke kolommen niet overeenkomen en corrigeer de doelkolommen zodat ze in alle gegevens van de bron passen. Gezien de metadatatoegang tot beide systemen en het feit dat je al een zoekopdracht schrijft die automatisch moet overeenkomen met de bron-> bestemmingskolommen (anders zou deze fout nauwelijks je grootste probleem zijn), zou je geen brute kracht moeten uitoefenen gissen.
Answer
Als je toegang hebt om de SQL Server Import and Export Wizard uit te voeren vanuit SQL Server Management Studio (klik met de rechtermuisknop op database> Taken> Gegevens importeren …), maak een taak die uit SQL Client wordt geïmporteerd met behulp van uw query als de gegevensbron naar de doeltabel.
Voordat u de import uitvoert, kunt u de gegevenstoewijzing bekijken en deze zal u vertellen welke kolommen inconsistente veldtypen hebben. En als u de importtaak uitvoert, zal het u vertellen welke kolom (men) niet konden worden geïmporteerd.
Voorbeeldvalidatiewaarschuwing:
Waarschuwing 0x802092a7: gegevensstroom Taak 1: afkapping kan optreden als gevolg van het invoegen van gegevens uit gegevensstroomkolom “NARRATIVE” met een lengte van 316 naar databasekolom “NARRATIVE” met een lengte van 60. (SQL Server Import and Export Wizard)
Antwoord
Eindelijk Microsoft heeft besloten om zinvolle informatie te verstrekken voor String or binary would be truncated
vanaf SQL Server 2016 SP2 CU, SQL Server 2017 CU12 en in SQL Server 2019.
De informatie bevat nu zowel de overtredende tabelkolom (volledig gekwalificeerde naam) als de overtredende waarde (afgekapt op 120 tekens):
Msg 2628, niveau 16, staat 1, Regel x String of binaire gegevens worden afgekapt in tabel “TheDb.TheSchema.TheTable “, column” TheColumn “. Afgekapte waarde:” … “. De instructie is beëindigd.
Antwoord
Uiteindelijk kon ik geen manier vinden om de kolominformatie te krijgen zonder deze zelf te schrijven.
Deze foutmelding is gegenereerd door DBD::ODBC
, je kunt echter ook sys.columns (max_length)
gebruiken (ik weet gewoon niet hoe).
Ik heb code als deze gebruikt over mijn kolomlijst om een lijst met arrays met twee elementen te krijgen, de COLUMN_NAME
, en MAX_LENGTH
(gedocumenteerd in DBI column_info()
).
my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ] , map $dbh_mssql->column_info("database", "dbo", $dest_table, $_) , @col_mssql ;
Toen ving ik de uitzonderingen op op INSERT
en drukte ik iets bruikbaars af. In dit voorbeeld zijn @$row
de gegevens verzonden naar 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; }
Stem ook en stem het andere antwoord omhoog.
sys.columns
omdat ik absoluut geen idee had welke code je momenteel gebruikt om ” automagisch ” uw zoekopdrachten genereren. Er is echt niet ‘ t te veel complexer die ik zou kunnen raden over het opnemen in je code danSELECT name, object_id, max_length FROM sys.columns;
. Aangezien je al automagische code hebt die dit moet doen – of iets heel vergelijkbaars – dacht ik ‘ niet dat een voorbeeld nodig was.sys.columns
werkt met twee kolommen die dezelfdename
hebben. Ook heb ik het ding laten werken door de bibliotheek te gebruiken in plaats vansys
, waarom zou ik dat als het gekozen antwoord maken?Microsoft SQL doesn't have x, do y instead
is een geldige bijdrage, maar als uwy
inferieur is aan mijny
, ‘ Ik ga iets anders doen en markeren als gekozen.