sql >> Database teknologi >  >> RDS >> Database

4 out-of-the-box SQL-datakonverteringsmetoder og brugssager

Først og fremmest kan du ikke undvære dem, vel?

SQL-datakonverteringer eller mere specifikt datatypekonverteringer er en væsentlig del af en databaseudviklers eller DBAs almindelige programmeringsarbejde.

Hvad nu hvis din chef underskrev en kontrakt med et andet firma om at give dem en fil i tekstformat, der kommer fra din SQL Server-database?

Det lyder som en spændende udfordring!

Men du fandt ud af, at du skulle håndtere en dato til en streng, et tal til en streng og en masse andre SQL-datakonverteringer. Er du stadig klar til udfordringen?

Ikke uden dit arsenal af datakonverteringstricks!

Hvad er tilgængeligt direkte fra kassen?

Da jeg startede med T-SQL-programmering, var den første ting, jeg så, der passede til formålet med konverteringen, CONVERT () funktion.

Desuden er ordet "konverter" der, ikke?

Selvom dette kan være sandt, er det blot en af ​​de 4 måder at udføre dette job på. Og jeg brugte det til næsten ALLE mine SQL-datakonverteringer. Jeg er glad for, at jeg er langt forbi det. Fordi jeg har lært, at de 4 metoder har deres egen plads i din kode.

Inden vi kommer til emnet for indlægget, lad mig præsentere de 4 out-of-the-box metoder til at udføre SQL-datakonvertering:

  • CAST ()
  • KONVERT ()
  • PARSE ()
  • TRY_CAST (), TRY_CONVERT (), TRY_PARSE ()

Hvert af afsnittene nedenfor vil:

  • Forklar, hvad det er
  • Fortæl dig, hvornår du skal bruge det (brugstilfælde)
  • Presenter dets begrænsninger
  • Giv eksempler og forklar det

Alt, der præsenteres i denne artikel, er så meget som muligt på almindeligt, simpelt engelsk. Når du er færdig med at læse hele indlægget, vil du vide, hvilken metode der er passende til en given situation.

Så lad os uden videre dykke ind.

1. SQL-datakonvertering ved hjælp af CAST()

Selvom alle de metoder, du vil se, kan konvertere datatyper, bør dit første valg til konvertering absolut være CAST ().

Her er grundene til:

  • Det er den hurtigst kørende konverteringsfunktion af alle. Vi vil forsøge at bevise dette senere i dette indlæg.
  • Det er inkluderet i SQL-92 sprogspecifikationsstandarder. Så når du skal portere din kode til andre SQL-produkter, såsom MySQL, er funktionen også tilgængelig.

Her er en meget enkel syntaks for CAST ():

CAST( <expression> AS <data_type>[(length)] ) 

Lad os først undersøge syntaksen:

  • <udtryk> er ethvert gyldigt udtryk, der resulterer i en værdi, der kan konverteres til måldatatypen.
  • <data_type> er måldatatypen.
  • længde er valgfri, og den vedrører størrelsen af ​​dataene.

Hvornår skal det bruges

Hvis det eneste, du skal bruge, er at konvertere en værdi til en anden datatype, så CAST () er lige hvad du har brug for.

Begrænsning

På den negative side, CAST () kan ikke give dig et formateret output direkte fra kassen som en formateret dato- og tidsværdi.

Eksempler

A. Konverter en streng til en dato:

SELECT CAST('09/11/2004 4:30PM' as datetime2) 

Og at køre ovenstående erklæring vil resultere i:

B. Konverter et tal til en streng:

SELECT CAST(10.003458802 as varchar(max)) 

Og resultatet af ovenstående konvertering er:

Nu, hvis du har brug for noget andet som at formatere de konverterede data, kan den næste metode hjælpe dig.

2. SQL-datakonvertering ved hjælp af CONVERT()

Den næste mulighed for datakonvertering er at bruge CONVERT (). Som jeg sagde før, er dette den, jeg brugte mest i de tidligere dage.

Her er syntaksen:

CONVERT( <data_type>[(length)], <expression> [, <style>]) 

Fra syntaksen ovenfor skal du være opmærksom på, at <stilen> parameter er valgfri. Og medmindre du angiver det, vil funktionen ligne CAST ().

Det var der, min forvirring begyndte, da jeg var ny til SQL.

Hvornår skal det bruges

Hvis du konverterer dataene med et øjeblikkeligt format, så KONVERT () er din ven. Hvilket betyder, at du behandler <stilen> parameter korrekt.

Begrænsninger

  • CAST () er hurtigere end CONVERTER (), så hvis du kun skal konvertere dataene, skal du bruge CAST (). Hvis outputtet skal formateres, skal du bruge CONVERT ().
  • KONVERT () er ikke en SQL-92-standard, så hvis du har brug for at portere den til andre RDBMS, skal du undgå at bruge den.

Eksempler

A. Konverter en dato til et strengformat ååååmmdd

I det følgende eksempel vil jeg bruge eksempeldatabasen AdventureWorks og transformer [StartDate ] kolonne til ååååmmdd :

USE AdventureWorks
GO
SELECT
[BillOfMaterialsID]
,CONVERT(varchar(10), [StartDate],112) as StartDate
FROM [Production].BillOfMaterials]
GO 

Bemærk at stil 112 bruges til at formatere datoer til åååmmdd .

B. Konverter et tal til en streng med kommaer på hvert tredje cifre til venstre for decimaltegnet.

På samme måde vil følgende eksempel illustrere AdventureWorks eksempeldatabase, og vi formaterer tallet med kommaer og med 2 decimaler.

USE AdventureWorks
GO
SELECT
[TransactionID]
,[ProductID]
,CONVERT(varchar(10),[TransactionDate] ,112) as StartDate
,[Quantity]
,CONVERT(varchar(10),[ActualCost],1) as ActualCost
FROM [Production].TransactionHistory
GO 

Bemærk, at format 1 bruges til [Faktiske omkostninger ]. Og tak til CONVERT (), kan vi formatere disse kolonner på et øjeblik.

Men hvad hvis du har brug for at konvertere et længere datoudtryk? Vil KONVERTERE () arbejde i så fald? Læs videre for at lære om den næste metode.

3. SQL-datakonvertering ved hjælp af PARSE()

Den næste metode, vi skal overveje, er PARSE ().

Tjek syntaksen:

PARSE( <string value> AS <datatype> [USING <culture>]) 

Hvornår skal det bruges

  • At konvertere strenge til datoer eller tal ved hjælp af en bestemt kultur.
  • Når strengen ikke kan konverteres til en dato eller et tal ved hjælp af CAST () eller KONVERT (). Se eksemplerne for at få flere oplysninger.

Begrænsninger

  • Konvertering er kun mulig for streng til datoer og streng til tal
  • Afhænger af tilstedeværelsen af ​​.Net Framework Common Language Runtime (CLR) på serveren.
  • Er ikke inkluderet i SQL-92 standardspecifikationer, så portering til andre RDBMS er et problem.
  • Har ydeevne overhead, når det kommer til at parse strengen.

Eksempler

A. Konvertering af en lang datostreng

SELECT PARSE('Monday, June 8, 2020' as datetime USING 'en-US') 

Eksemplet ovenfor er en lang datostreng, der skal konverteres til en datetime værdi ved at bruge amerikansk engelsk kultur. Og det er her PARSE () vil gøre sit bedste.

Det er fordi koden ovenfor mislykkes, hvis du bruger CAST () eller KONVERT ().

B. Konvertering af en pengeværdi med et valutasymbol

SELECT PARSE('€1024,01' as money using 'de-DE') 

Prøv nu at udføre konverteringen ved hjælp af CAST () og KONVERT ()

SELECT CONVERT(money,'€1024,01')
SELECT CAST('€1024,01' as money) 

Udsagnet vil ikke give fejl, men tag et kig på dette uventede resultat:

Som følge heraf er værdien blevet konverteret til 102401.00 i stedet for 1024.01.

Indtil videre har vi opdaget, at de første 3 metoder er tilbøjelige til fejl, medmindre du tjekker dem. Ikke desto mindre kan den 4. metode være din løsning på det fejlbehæftede resultat.

4. SQL-datakonvertering ved hjælp af TRY_CAST(), TRY_CONVERT() eller TRY_PARSE()

Endelig er den sidste metode til SQL-datakonvertering at bruge en variant af de første 3, men med præfikset TRY_.

Men alligevel, hvad er forskellen?

De har de samme parametre som de foregående 3 uden præfikset TRY_. Men forskellen er, at de returnerer NULL hvis værdien ikke kan konverteres. Nu, hvis værdien ikke kan konverteres af nogen af ​​de 3 eksplicit, opstår der en fejl. Se eksemplerne nedenfor for en bedre forståelse.

Hvornår skal det bruges

Du kan bruge enhver af de 3 med betingede udsagn som CASE HVORNÅR eller IIF for at teste for fejl.

Begrænsninger

De 3 af dem har de samme begrænsninger som dem uden TRY_-præfikset, bortset fra værdier, der ikke kan konverteres.

Eksempler

A. Brug TRY_CAST() til at teste, om konverteringen vil lykkes ved hjælp af IIF:

SELECT IIF(TRY_CAST('111b' AS real) IS NULL, 'Cast failed', 'Cast succeeded') AS Result 

Koden ovenfor returnerer "Cast mislykkedes", fordi "111b" ikke kan konverteres til rigtig . Fjern 'b'et' fra værdien, og det vil returnere 'Cast succeeded'.

B. Brug af TRY_CONVERT() på datoer med et bestemt format

SET DATEFORMAT dmy;
SELECT TRY_CONVERT(datetime2, '12/31/2010') AS Result 

Dette vil returnere NULL fordi formatet bruger dmy eller dag-måned-år. Og inputudtrykket for TRY_CONVERT () er i formatet mdy eller måned-dag-år. Fejlen blev udløst, fordi månedsværdien er 31.

C. Bruger TRY_PARSE(), der vil generere en runtime-fejl

SELECT
CASE WHEN TRY_PARSE('10/21/2133' AS smalldatetime USING 'en-US') IS NULL
    THEN 'True'
    ELSE 'False'
END AS Result 

Denne kode vil generere en runtime fejl som vist nedenfor:

Det er det for de 4 out-of-the-box metoder i SQL datakonvertering. Men der er mere på vej.

Hvad med SQL-datakonvertering ved hjælp af implicit konvertering?


Lad os nu overveje implicit konvertering. Dette er en tavs metode.

Hvorfor stille?

Fordi du måske allerede gør det, men du er ikke klar over det. Eller i det mindste, du ved, at det sker, men du ignorerer det.

Det er med andre ord den type konvertering, som SQL automatisk udfører uden nogen funktioner.

Lad mig give dig et eksempel:

DECLARE @char CHAR(25)
DECLARE @varchar VARCHAR(25)
DECLARE @nvarchar NVARCHAR(25)
DECLARE @nchar NCHAR(25)
 
SET @char = 'Live long and prosper'
SET @varchar = @char
SET @nvarchar = @varchar
SET @nchar = @nvarchar
 
SELECT @char AS [char], @varchar AS [varchar], @nvarchar AS [nvarchar], @nchar AS [nchar] 

Ovenstående kode vil blive eksekveret med succes. Prøv det selv, og du vil få et resultat svarende til nedenstående:

Lad os prøve dette med datoer:

DECLARE @datetime datetime
DECLARE @smalldatetime smalldatetime
DECLARE @datetime2 datetime2

SET @datetime = '12/31/2050 14:34'
SET @smalldatetime = @datetime
SET @datetime2 = @smalldatetime

SELECT @datetime as [datetime], @smalldatetime as [smalldatetime], @datetime2 as [datetime2] 

Som forventet vil dette give et vellykket resultat:

Lad os prøve det denne gang med tal:

DECLARE @int int
DECLARE @real real
DECLARE @decimal decimal
DECLARE @float float

SET @int = 1701
SET @real = @int
SET @decimal = @real
SET @float = @decimal

SELECT @int as [int], @real as [real], @decimal as [decimal], @float as [float] 

Stadig en succes, ikke?

Indtil videre har vi brugt simple værdier, der vil være velegnede til en ret lignende type data. Lad os komme ind på næste niveau:tal til strenge.

DECLARE @number int
DECLARE @string varchar(5)

SET @number = 1701
SET @string = @number

SELECT @number as [number], @string as [string] 

Dette vil blive konverteret med succes, som du kan se fra resultatet nedenfor:

Der er mange flere tilfælde, hvor SQL Server vil forsøge at "gætte", hvordan man konverterer data. Som du kan se fra denne reference, er der mange tilfælde sammenlignet med dem, der kræver eksplicit konvertering.

Da SQL Server tillader dette, betyder det, at du frit kan tillade, at dette sker overalt i din kode?

Forbehold i implicit konvertering

For det første kan det være praktisk. Men når grænserne for hver datatype er nået, vil du indse, at implicit konvertering er lidt farlig, hvis den ikke er markeret.

Overvej et eksempel nedenfor:

DECLARE @char char(25)
DECLARE @varchar varchar(25)
DECLARE @nvarchar nvarchar(25)
DECLARE @nchar nchar(25)

SET @nvarchar = N'I ❤ U!'
SET @nchar = @nvarchar 
SET @char = @nchar
SET @varchar = @nchar

SELECT @char as [char], @varchar as [varchar], @nvarchar as [nvarchar], @nchar as [nchar] 

Så du emoji-værdien? Det tæller som en unicode-værdi.

Mens alle ovenstående udsagn vil køre med succes, variabler med ikke-unicode-typer som varchar og char vil have uventede resultater. Se resultatet nedenfor:

Ikke desto mindre er det ikke det eneste problem. Fejl vil poppe ud, når værdien bliver uden for området. Overvej et eksempel med datoer:

DECLARE @datetime datetime
DECLARE @smalldatetime smalldatetime
DECLARE @datetime2 datetime2

SET @datetime = '12/31/2374 14:34'
SET @smalldatetime = @datetime
SET @datetime2 = @smalldatetime

SELECT @datetime as [datetime], @smalldatetime as [smalldatetime], @datetime2 as [datetime2] 

Tildelingen af ​​datetime værdi til smalldatetime variabel vil udløse fejlen, som du kan se nedenfor:

Men der er en anden advarsel, som du også bør være opmærksom på, når du beskæftiger dig med implicit konvertering:præstationsomkostninger. Da dette er et varmt emne, fortjener det at have et separat afsnit.

Ydeevneimplikationer af forskellige SQL-datakonverteringsmetoder

Tro det eller ej, forskellige SQL-datakonverteringsmetoder vil have forskellig ydeevne i faktiske situationer. Og du bør i det mindste være opmærksom på dette, så du kan undgå præstationsfælder.

Hvordan CAST(), CONVERT() og PARSE() udføres

Lad os først undersøge, hvordan CAST (), KONVERT (), og PARSE () præstere under naturlige forhold ved at sammenligne, hvad der er hurtigere. Vi tilpasser og beviser konceptet for vores eksempel taget herfra. Overvej koden nedenfor:

USE AdventureWorks GO SET STATISTICS TIME ON SELECT CAST([NationalIDNumber] as int) FROM [HumanResources].[Employee] SELECT CONVERT(int,[NationalIDNumber]) FROM [HumanResources].[Employee] SELECT PARSE([NationalIDNumber] as int) FROM [HumanResources].[Employee] SET STATISTICS TIME OFF GO

Lad os nu undersøge koden, der bruger AdventureWorks database fra Microsoft:

  • INDSTILL STATISTIK TID TIL vil udlæse CPU-tiden og den forløbne tid i hver af SELECT udsagn
  • Derefter er den kolonne, vi vælger at konvertere til demonstrationsformål, [NationalIDNumber ], som har en type nvarchar(15) .
  • Konverteringen er også fra en streng til et heltal:nvarchar(15) til int .
  • Og til sidst gendanner vi SET STATISTICS TIME til sin tidligere værdi

Læg mærke til outputtet i Beskeder fanen i forespørgselsresultatet:

Her er, hvad vi er kommet frem til ved hjælp af dette eksempel:

  • Det beviser, at CAST () udfører den hurtigste (1 ms.) og PARSE () udfører den langsomste (318 ms.).
  • Vi følger denne prioritet, når vi beslutter, hvilken funktion der skal bruges til at konvertere data:(1 ) CAST () (2 ) KONVERT () (3 ) PARSE ().
  • Husk, hvornår hver funktion er relevant, og overvej begrænsningerne, når du beslutter, hvilken funktion der skal bruges.

Hvordan implicit konvertering udføres

På dette tidspunkt burde du kunne se, at jeg anbefaler brugen af ​​funktioner som CAST() til at konvertere data. Og i dette afsnit vil du se hvorfor.

Overvej denne forespørgsel ved at bruge WideWorldImporters database fra Microsoft. Inden du udfører den, skal du aktivere Inkluder faktisk udførelsesplan i SQL Server Management Studio .

USE WideWorldImporters
GO
SELECT
[CustomerID]
,[OrderID]
,[OrderDate]
,[ExpectedDeliveryDate]
FROM [Sales].[Orders]
WHERE [CustomerID] like '487%' 

I forespørgslen ovenfor filtrerer vi resultatet af salgsordrer med [CustomerID ] som '487 %'. Det er blot for at demonstrere, hvilken effekt den implicitte konvertering af en int datatypen har på varchar .

Dernæst gennemgår vi nedenstående udførelsesplan:

Som du kan se, er der en advarsel i SELECT ikon. Hold derfor musen over for at se værktøjstip. Læg derefter mærke til advarselsmeddelelsen, nemlig CONVERT_IMPLICIT .

Før vi fortsætter, denne CONVERT_IMPLICIT advarsel opstår, når det er nødvendigt at udføre en implicit konvertering til SQL Server. Lad os se nærmere på problemet. Som beskrevet nedenfor har advarslen 2 dele:

  • CONVERT_IMPLICIT kan påvirke "CardinalityEstimate" i en forespørgselsplanvalg.
  • CONVERT_IMPLICIT kan påvirke "SeekPlan" i en forespørgselsplanvalg.

Begge angiver, at din forespørgsel vil køre langsommere. Men vi ved selvfølgelig hvorfor. Vi fremtvinger bevidst en implicit konvertering ved at bruge et LIKE operator for en heltalsværdi.

Hvad er meningen med det?

  • Implicit konvertering af data får SQL Server til at bruge CONVERT_IMPLICIT , hvilket forsinker udførelsen af ​​din forespørgsel.
  • For at løse dette problem skal du fjerne brugen af ​​implicit konvertering. I vores tilfælde brugte vi [CustomerID ] LIKE '487%', vi kan rette det ved at ændre [Kunde-ID ] =487. Rettelse af forespørgslen vil ændre forespørgselsudførelsesplanen, fjerne advarslen tidligere og ændre indeksscanningsoperatoren til en indekssøgning. I sidste ende forbedres ydeevnen.

Lykkelig slutning? Ja!

Takeaways

Som vist kan vi ikke bare lade SQL Server udføre konverteringen med en implicit konvertering. Jeg anbefaler dig at følge forrangen, når det kommer til at beslutte, hvad du skal bruge, når du konverterer data.

  • For det første, hvis du bare skal konvertere, som det er, skal du bruge CAST (). Det er en mere standardiseret funktion, når det drejer sig om portering til andre RDBM'er.
  • For det andet, hvis du har brug for formaterede data, skal du bruge KONVERT ().
  • For det tredje, hvis begge CAST () og KONVERT () undlader at udføre jobbet, brug PARSE ().
  • Til sidst, for at teste for fejl ved konvertering, brug TRY_CAST (), TRY_CONVERT (), eller TRY_PARSE ().

Nå, det var alt for nu. Jeg håber, at dette hjælper dig med dine næste kodeeventyr. Brække et ben!

For at lære mere om emnet SQL-datakonvertering fra Microsoft:

  • CAST og KONVERTER
  • PARSE
  • TRY_CAST, TRY_CONVERT og TRY_PARSE

  1. En databasemodel til en onlineundersøgelse. Del 4

  2. SQL Server Temporary Object Caching

  3. Hvordan kan sanitet, der undslipper enkelte anførselstegn, besejres af SQL-injektion i SQL Server?

  4. Tæl forekomsten af ​​DISTINCT-værdier