Hvordan identificerer jeg de (n) kolonne (r), der er ansvarlige for “ Streng eller binære data vil blive afkortet. ”

Jeg genererer nogle forespørgsler automatisk med kode, som jeg skrev til SELECT fra en ekstern Pg-database, og indsatte i en lokal SQL Server-database. En af dem genererer dog denne fejl:

[Microsoft] [ODBC SQL Server Driver] [SQL Server] Streng eller binære data vil blive afkortet. (SQL-22001) [tilstand var 22001 nu 01000]

[Microsoft] [ODBC SQL Server Driver] [SQL Server] Erklæringen er afsluttet. (SQL-01000) ved. \ Insert.pl linje 106.

Hvordan finder jeg ud af, hvilken kolonne der genererer den fejl, og mangler længden for input? Er der en måde at gøre dette på uden at gætte alt varchar?

Svar

Nej, det er ikke logget nogen steder. Gå til at stemme og opgiv din forretningssag; dette er en på den lange liste over ting, der skal rettes i SQL Server.

Dette blev anmodet om for mange år siden på Connect (sandsynligvis først i SQL Server 2000 eller 2005-tidsrammen) og derefter igen på det nye feedback-system:

Og nu er den leveret i følgende versioner:

I den allerførste offentlige CTP i SQL Server 2019 overflader den kun under sporflag 460. Dette lyder lidt hemmeligt, men det blev offentliggjort i denne Microsoft whitepaper . Dette vil være standardadfærden (ingen sporingsflag kræves) fremadrettet, selvom du vil være i stand til at styre dette via en ny database-konfigureret konfiguration VERBOSE_TRUNCATION_WARNINGS.

Her er et eksempel:

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

Resultat i alle understøttede versioner før SQL Server 2019:

Msg 8152, niveau 16, tilstand 30, linje 5
Streng eller binære data vil blive afkortet.
Erklæringen er afsluttet.

Nu, på SQL Server 2019 CTPer, med sporingsflag aktiveret:

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

Resultatet viser tabellen, kolonnen og ( trunkeret , ikke fuld ) værdi:

Msg 2628, niveau 16, tilstand 1, linje 11
String- eller binære data vil blive afkortet i tabellen “tempdb.dbo.x”, kolonne “a”. Afkortet værdi: “f”.
Erklæringen er afsluttet.

Indtil du kan flytte til en understøttet version / CU eller flytte til Azure SQL Database, kan du ændre din “automagisk” kode for faktisk at trække max_length fra sys.columns sammen med det navn, som du alligevel skal komme derhen, og derefter anvende LEFT(column, max_length) eller hvad PG svarer til. Eller, da det bare betyder, at du stille vil miste data, skal du finde ud af, hvilke kolonner der er uoverensstemmende, og rette destinationskolonnerne, så de passer til alle data fra kilden. Givet metadataadgang til begge systemer og det faktum, at du allerede skriver en forespørgsel, der automatisk skal matche kilde -> destinationskolonner (ellers ville denne fejl næppe være dit største problem), skulle du ikke skulle udføre nogen brutal kraft gætte overhovedet.

Svar

Hvis du har adgang til at køre SQL Server import- og eksportguide fra SQL Server Management Studio (højreklik på database> Opgaver> Importer data …), skal du oprette en opgave, der importeres fra SQL Client ved hjælp af din forespørgsel som datakilde til destinationstabellen.

Før du kører importen, kan du gennemse datakortlægningen, og den fortæller dig, hvilke kolonner der har inkonsekvente felttyper. Og hvis du kører importopgaven, fortæller den dig, hvilke kolonner der ikke kunne importeres.

Advarsel om validering af prøve:

Advarsel 0x802092a7: Datastrømningsopgave 1: Afkortning kan forekomme på grund af indsættelse af data fra datastrømskolonnen “NARRATIVE” med en længde på 316 til databasekolonnen “NARRATIVE” med en længde på 60. (SQL Server Import og eksport-guide)

Svar

Endelig Microsoft har besluttet at give meningsfuld information til String or binary would be truncated startende fra SQL Server 2016 SP2 CU, SQL Server 2017 CU12 og i SQL Server 2019.

Oplysningerne inkluderer nu både fornærmende tabelkolonne (fuldt kvalificeret navn) og den krænkende værdi (afkortet med 120 tegn):

Msg 2628, niveau 16, tilstand 1, Linje x streng eller binære data vil blive afkortet i tabellen “TheDb.TheSchema.TheTable “, kolonne” TheColumn “. Afkortet værdi:” … “. Erklæringen er afsluttet.

Svar

I sidste ende kunne jeg ikke finde en måde at få kolonneoplysningerne uden at skrive det selv.

Denne fejlmeddelelse blev genereret af DBD::ODBC , du kan dog også bruge sys.columns (max_length) (jeg ved bare ikke hvordan).

Jeg brugte kode som denne over min kolonneliste for at få en liste med arrays med to elementer, COLUMN_NAME og MAX_LENGTH (dokumenteret i DBI column_info() ).

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

Så fangede jeg undtagelserne på INSERT og udskrev noget nyttigt. I dette eksempel er @$row dataene sendt til 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; } 

Du skal også stemme og stemme det andet svar

Kommentarer

  • I lagde ikke ‘ nogen kode, der refererer til sys.columns, fordi jeg ikke havde nogen idé om, hvilken kode du i øjeblikket bruger til ” genererer automatisk dine forespørgsler “. Der er virkelig ikke ‘ t for meget mere komplekst, jeg kunne gætte om at indarbejde i din kode end SELECT name, object_id, max_length FROM sys.columns;. Da du allerede har en automagisk kode, der skal gøre dette – eller noget der ligner det meget – troede jeg ikke ‘ at et eksempel var nødvendigt.
  • I ‘ Jeg er ikke sikker på, hvordan sys.columns fungerer med to kolonner, der har den samme name. Jeg fik også tingene ved at bruge biblioteket i stedet for sys, hvorfor skulle jeg gøre det som det valgte svar? Microsoft SQL doesn't have x, do y instead er et gyldigt bidrag, men hvis din y er ringere end min y, ‘ skal gøre noget andet og markere det som valgt.
  • Dit spørgsmål var i det væsentlige, hvordan finder jeg ud af, hvilken kolonne der genererede fejlen (formodentlig , så du kunne rette det ene sted i stedet for at ombygge løsningen). Jeg fortalte dig, hvor du skulle kigge: sys.column. Hvilket er nøjagtigt, hvor du skal se for at sammenligne dine kildekolonnelængder med destinationskolonnelængderne. Hvordan du gør det er op til dig. Jeg fortalte dig ikke ‘, hvordan jeg fikser din kode, for jeg har absolut ingen idé om, hvordan din automatiske forespørgsel blev genereret i første omgang, så som jeg sagde, havde jeg ingen idé om, hvordan for at tilføje længdebestemmelserne til den forespørgsel, du allerede havde.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *