Hoe identificeer ik de kolom (men) die verantwoordelijk is voor “ String- of binaire gegevens zouden worden afgekapt. ”

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.

Opmerkingen

  • I didn ‘ t geen code plaatsen die verwijst naar 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 dan SELECT 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.
  • I ‘ m niet zeker hoe sys.columns werkt met twee kolommen die dezelfde name hebben. Ook heb ik het ding laten werken door de bibliotheek te gebruiken in plaats van sys, waarom zou ik dat als het gekozen antwoord maken? Microsoft SQL doesn't have x, do y instead is een geldige bijdrage, maar als uw y inferieur is aan mijn y, ‘ Ik ga iets anders doen en markeren als gekozen.
  • Je vraag was in wezen: hoe kom ik erachter welke kolom de fout veroorzaakte (vermoedelijk , zodat u die ene plek kunt repareren in plaats van de oplossing opnieuw te ontwerpen). Ik zei je waar je moest zoeken: sys.columns. Dat is precies waar u moet zoeken om de lengte van uw bronkolom te vergelijken met de lengte van de bestemmingskolom. Hoe je dat doet, is aan jou. Ik heb je ‘ niet verteld hoe je je code moet repareren, omdat ik absoluut geen idee heb hoe je automagische zoekopdracht werd gegenereerd, dus, zoals ik al zei, had ik geen idee hoe om de lengtebepalingen toe te voegen aan elke zoekopdracht die u al had.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *