Jeg genererer noen spørsmål automatisk med kode jeg skrev til SELECT fra en ekstern Pg-database, og setter inn i en lokal SQL Server-database. En av dem genererer imidlertid denne feilen:
[Microsoft] [ODBC SQL Server Driver] [SQL Server] Streng eller binære data vil bli avkortet. (SQL-22001) [tilstand var 22001 nå 01000]
[Microsoft] [ODBC SQL Server Driver] [SQL Server] Uttalelsen er avsluttet. (SQL-01000) på. \ Insert.pl linje 106.
Hvordan finner jeg ut hvilken kolonne som genererer den feilen og mangler lengden på innspill? Er det en måte å gjøre dette uten å tippe alle varchar
?
Svar
Nei, den er ikke logget hvor som helst. Gå til å stemme og oppgi din sak; dette er en på den lange listen over ting som skal løses i SQL Server.
Dette ble bedt om for mange år siden på Connect (sannsynligvis først i tidsrammen for SQL Server 2000 eller 2005), og deretter igjen på det nye tilbakemeldingssystemet:
Og nå har den blitt levert i følgende versjoner:
I den aller første offentlige CTP av SQL Server 2019, dukker den bare opp under sporingsflagg 460. Dette høres ut som en hemmelighet, men den ble publisert i denne Microsoft-papiret . Dette vil være standard oppførsel (ingen sporingsflagg kreves) fremover, selv om du vil kunne kontrollere dette via en ny databasekonfigurasjon 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 støttede versjoner før SQL Server 2019:
Msg 8152, nivå 16, tilstand 30, linje 5
String- eller binærdata vil bli avkortet.
Uttalelsen er avsluttet.
Nå, på CTP-er for SQL Server 2019, med sporingsflagget aktivert:
DBCC TRACEON(460); GO INSERT dbo.x(a) VALUES("foo"); GO DROP TABLE dbo.x; DBCC TRACEOFF(460);
Resultatet viser tabellen, kolonnen og ( avkortet , ikke full ) verdi:
Msg 2628, nivå 16, tilstand 1, linje 11
Streng- eller binærdata vil bli avkortet i tabellen «tempdb.dbo.x», kolonne «a». Avkortet verdi: «f».
Uttalelsen er avsluttet.
Inntil du kan flytte til en støttet versjon / CU, eller flytte til Azure SQL Database, kan du endre din «automagic» kode for å faktisk trekke maks_lengden fra sys.columns
, sammen med navnet som du uansett må komme dit, og deretter bruke LEFT(column, max_length)
eller hva PG tilsvarer. Eller, siden det bare betyr at du taper data, kan du finne ut hvilke kolonner som ikke samsvarer, og fikse destinasjonskolonnene slik at de passer til alle dataene fra kilden. Gitt metadatatilgang til begge systemene, og det faktum at du allerede skriver et spørsmål som automatisk må matche kilde -> destinasjonskolonner (ellers vil denne feilen neppe være ditt største problem), bør du ikke trenge å gjøre noen brute-force gjetting i det hele tatt.
Svar
Hvis du har tilgang til å kjøre SQL Server Import and Export Wizard fra SQL Server Management Studio (høyreklikk database> Oppgaver> Importer data …), opprett en oppgave som importeres fra SQL Client ved å bruke spørringen din som datakilde til måltabellen.
Før du kjører importen, kan du gå gjennom datakartleggingen, og den vil fortelle deg hvilke kolonner som har inkonsekvente felttyper. Og hvis du kjører importoppgaven, vil den fortelle deg hvilken kolonne (r) som ikke kunne importeres.
Eksempelvalideringsadvarsel:
Advarsel 0x802092a7: Datastrømningsoppgave 1: Avkorting kan oppstå på grunn av innsetting av data fra datastrømkolonnen «NARRATIVE» med lengden 316 i databasekolonnen «NARRATIVE» med lengden 60. (SQL Server Import og eksport-veiviser)
Svar
Endelig Microsoft har besluttet å gi meningsfull informasjon for String or binary would be truncated
startende fra SQL Server 2016 SP2 CU, SQL Server 2017 CU12 og i SQL Server 2019.
Informasjonen inkluderer nå både krenkende tabellkolonne (fullt kvalifisert navn) og krenkende verdi (avkortet med 120 tegn):
Msg 2628, nivå 16, tilstand 1, Linje x streng eller binære data vil bli avkortet i tabellen «TheDb.TheSchema.TheTable «, kolonne» TheColumn «. Avkortet verdi:» … «. Uttalelsen er avsluttet.
Svar
Til slutt kunne jeg ikke finne en måte å få kolonneinformasjonen uten å skrive den selv.
Denne feilmeldingen ble generert av DBD::ODBC
, men du kan også bruke sys.columns (max_length)
(jeg vet bare ikke hvordan).
Jeg brukte kode som denne over kolonnelisten min for å få en liste med matriser med to elementer, COLUMN_NAME
og MAX_LENGTH
(dokumentert 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å fanget jeg unntakene på INSERT
og skrev ut noe nyttig. I dette eksemplet 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; }
Stem og stem opp det andre svaret
sys.columns
fordi jeg hadde ingen anelse om hvilken kode du bruker for øyeblikket til » genererer automatisk spørsmålene dine «. Det er virkelig ikke ‘ t for mye mer komplekst jeg kunne gjette om å innlemme i koden din ennSELECT name, object_id, max_length FROM sys.columns;
. Siden du allerede har en automagisk kode som må gjøre dette – eller noe som ligner mye på det – trodde jeg ikke ‘ at et eksempel var nødvendig.sys.columns
fungerer med to kolonner som har sammename
. Også fikk jeg tingen til å bruke biblioteket i stedet forsys
, hvorfor skulle jeg gjøre det som det valgte svaret?Microsoft SQL doesn't have x, do y instead
er et gyldig bidrag, men hvisy
er dårligere enny
, ‘ skal gjøre noe annerledes og merke det som valgt.