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
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 endSELECT 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.sys.columns
fungerer med to kolonner, der har den sammename
. Jeg fik også tingene ved at bruge biblioteket i stedet forsys
, 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 diny
er ringere end miny
, ‘ skal gøre noget andet og markere det som valgt.