sql >> Database >  >> RDS >> Database

4 kant-en-klare SQL-gegevensconversiemethoden en gebruiksscenario's

Allereerst kun je niet zonder, toch?

SQL-gegevensconversies of, meer specifiek, gegevenstypeconversies zijn een essentieel onderdeel van het reguliere programmeerwerk van een databaseontwikkelaar of DBA.

Wat als uw baas een contract heeft getekend met een ander bedrijf om hen een bestand in tekstformaat te verstrekken dat afkomstig is uit uw SQL Server-database?

Dit klinkt als een spannende uitdaging!

Maar je ontdekte dat je te maken zou krijgen met een datum naar een string, een nummer naar een string en een heleboel andere SQL-gegevensconversies. Ga je de uitdaging nog steeds aan?

Niet zonder je arsenaal aan gegevensconversietrucs!

Wat is er standaard beschikbaar?

Toen ik voor het eerst met T-SQL-programmering begon, was het eerste dat ik zag dat bij het doel van de conversie paste de CONVERT () functie.

Trouwens, het woord "converteren" is er, toch?

Hoewel dit misschien waar is, is het slechts een van de 4 manieren om deze taak uit te voeren. En ik gebruikte het voor bijna AL mijn SQL-gegevensconversie. Ik ben blij dat ik daar ver voorbij ben. Omdat ik heb geleerd dat de 4 methoden hun eigen plaats hebben in je code.

Voordat we naar het onderwerp van het bericht gaan, wil ik u de 4 kant-en-klare methoden presenteren om SQL-gegevensconversie uit te voeren:

  • CAST ()
  • CONVERTEREN ()
  • PASEREN ()
  • TRY_CAST (), TRY_CONVERT (), TRY_PARSE ()

Elk van de onderstaande secties zal:

  • Leg uit wat het is
  • U vertellen wanneer u het moet gebruiken (gebruiksscenario's)
  • De beperkingen aangeven
  • Geef voorbeelden en leg het uit

Alles wat in dit artikel wordt gepresenteerd, is zoveel mogelijk in gewoon, eenvoudig Engels. Tegen de tijd dat je het hele bericht hebt gelezen, weet je welke methode geschikt is voor een bepaalde situatie.

Dus, zonder verder oponthoud, laten we erin duiken.

1. SQL-gegevensconversie met CAST()

Hoewel alle methoden die u zult zien gegevenstypen kunnen converteren, moet uw eerste keuze bij het converteren zeker CAST zijn ().

Dit zijn de redenen waarom:

  • Het is de snelst werkende conversiefunctie van allemaal. We zullen dit later in dit bericht proberen te bewijzen.
  • Het is opgenomen in de taalspecificatiestandaarden van SQL-92. Dus als u uw code moet overdragen naar andere SQL-producten, zoals MySQL, is de functie ook beschikbaar.

Hier is een heel eenvoudige syntaxis voor CAST ():

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

Laten we eerst de syntaxis eens bekijken:

  • <uitdrukking> is een geldige uitdrukking die resulteert in een waarde die kan worden geconverteerd naar het doelgegevenstype.
  • <data_type> is het doelgegevenstype.
  • lengte is optioneel en heeft betrekking op de grootte van de gegevens.

Wanneer te gebruiken

Als u alleen een waarde naar een ander gegevenstype hoeft te converteren, dan CAST () is precies wat je nodig hebt.

Beperking

Aan de negatieve kant, CAST () kan je geen geformatteerde output geven, zoals een geformatteerde datum- en tijdwaarde.

Voorbeelden

A. Converteer een string naar een datum:

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

En het uitvoeren van de bovenstaande verklaring zal resulteren in:

B. Converteer een getal naar een tekenreeks:

SELECT CAST(10.003458802 as varchar(max))

En het resultaat van de bovenstaande conversie is:

Als u nu iets anders nodig heeft, zoals het formatteren van de geconverteerde gegevens, kan de volgende methode u helpen.

2. SQL-gegevensconversie met CONVERT()

De volgende optie voor gegevensconversie is om CONVERT . te gebruiken (). Zoals ik al eerder zei, dit is degene die ik vroeger het meest gebruikte.

Dit is de syntaxis:

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

Houd er in de bovenstaande syntaxis rekening mee dat de <stijl> parameter is optioneel. En tenzij je het opgeeft, zal de functie vergelijkbaar zijn met CAST ().

Daar begon mijn verwarring toen ik nog niet bekend was met SQL.

Wanneer te gebruiken

Als u de gegevens converteert met een instant-indeling, dan CONVERT () is jouw vriend. Wat betekent dat je de <stijl . behandelt> parameter correct.

Beperkingen

  • CAST () is sneller dan CONVERT (), dus als u alleen de gegevens hoeft te converteren, gebruikt u CAST (). Als de uitvoer moet worden geformatteerd, gebruik dan CONVERT ().
  • CONVERTEREN () is geen SQL-92-standaard, dus als u het naar andere RDBMS moet porten, gebruik het dan niet.

Voorbeelden

A. Converteer een datum naar een tekenreeksformaat jjjjmmdd

In het volgende voorbeeld gebruik ik de voorbeelddatabase AdventureWorks en transformeer de [StartDate ] kolom naar jjjjmmdd :

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

Merk op dat stijl 112 wordt gebruikt voor het opmaken van datums tot jjjjmmdd .

B. Converteer een getal naar een tekenreeks met komma's op elke 3 cijfers links van de komma.

Evenzo illustreert het volgende voorbeeld de AdventureWorks voorbeelddatabase, en we zullen het getal opmaken met komma's en met 2 decimalen.

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

Merk op dat formaat 1 wordt gebruikt voor [Werkelijke kosten ]. En dankzij CONVERT (), we kunnen deze kolommen in een oogwenk opmaken.

Maar wat als u een langere datum-expressie moet converteren? Zal CONVERTEREN () werken in dat geval? Lees verder voor meer informatie over de volgende methode.

3. SQL-gegevensconversie met PARSE()

De volgende methode die we gaan overwegen is PARSE ().

Bekijk de syntaxis:

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

Wanneer te gebruiken

  • Om tekenreeksen om te zetten in datums of getallen met een specifieke cultuur.
  • Als de tekenreeks niet kan worden geconverteerd naar een datum of een getal met CAST () of CONVERTEREN (). Bekijk de voorbeelden voor meer informatie.

Beperkingen

  • Conversie is alleen mogelijk voor string naar datums en string naar getallen
  • Vertrouwt op de aanwezigheid van .Net Framework Common Language Runtime (CLR) op de server.
  • Is niet opgenomen in de standaardspecificaties van SQL-92, dus overzetten naar andere RDBMS is een probleem.
  • Heeft prestatie-overhead als het gaat om het ontleden van de string.

Voorbeelden

A. Een lange datumreeks converteren

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

Het bovenstaande voorbeeld is een lange datumreeks die moet worden geconverteerd naar een datetime waarde met behulp van de Amerikaans-Engelse cultuur. En dit is waar PARSE () zal zijn best doen.

Dat komt omdat de bovenstaande code zal mislukken als je CAST . gebruikt () of CONVERTEREN ().

B. Een geldwaarde omrekenen met een valutasymbool

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

Probeer nu de conversie uit te voeren met CAST () en CONVERTEREN ()

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

De verklaring zal geen fouten veroorzaken, kijk toch eens naar dit onverwachte resultaat:

Als gevolg hiervan is de waarde geconverteerd naar 102401.00 in plaats van 1024.01.

Tot nu toe hebben we ontdekt dat de eerste 3 methoden gevoelig zijn voor fouten, tenzij u ze controleert. Desalniettemin kan de vierde methode uw oplossing zijn voor het defecte resultaat.

4. SQL-gegevensconversie met TRY_CAST(), TRY_CONVERT() of TRY_PARSE()

Ten slotte is de laatste methode voor SQL-gegevensconversie het gebruik van een variant van de eerste 3 maar met het voorvoegsel TRY_.

Maar toch, wat is het verschil?

Ze hebben dezelfde parameters als de vorige 3 zonder het voorvoegsel TRY_. Maar het verschil is, ze retourneren NULL als de waarde niet kan worden geconverteerd. Als de waarde nu niet expliciet door een van de 3 kan worden geconverteerd, treedt er een fout op. Bekijk de voorbeelden hieronder voor een beter begrip.

Wanneer te gebruiken

U kunt elk van de 3 gebruiken met voorwaardelijke uitspraken zoals CASE WANNEER of IIF om te testen op fouten.

Beperkingen

De drie hebben dezelfde beperkingen als die zonder het voorvoegsel TRY_, behalve voor waarden die niet kunnen worden geconverteerd.

Voorbeelden

A. Gebruik TRY_CAST() om te testen of de conversie zal slagen met IIF:

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

De bovenstaande code retourneert 'Cast Failed' omdat '111b' niet kan worden geconverteerd naar echt . Haal de 'b' van de waarde weg, en het zal 'Cast geslaagd' retourneren.

B. TRY_CONVERT() gebruiken op datums met een specifieke notatie

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

Dit geeft NULL . terug omdat het formaat dmy . gebruikt of dag-maand-jaar. En de invoerexpressie voor TRY_CONVERT () heeft de indeling mdy of maand-dag-jaar. De fout is geactiveerd omdat de maandwaarde 31 is.

C. TRY_PARSE() gebruiken die een runtime-fout genereert

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

Deze code genereert een runtime-fout zoals hieronder te zien is:

Dat is het voor de 4 kant-en-klare methoden in SQL-gegevensconversie. Maar er komt nog meer.

Hoe zit het met SQL-gegevensconversie met behulp van impliciete conversie?


Laten we nu eens kijken naar impliciete conversie. Dit is een stille methode.

Waarom stil?

Omdat je het misschien al doet, maar je je er niet van bewust bent. Of je weet tenminste dat het gebeurt, maar je negeert het.

Met andere woorden, dit is het type conversie dat SQL automatisch uitvoert zonder enige functies.

Laat me je een voorbeeld geven:

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]

De bovenstaande code wordt met succes uitgevoerd. Probeer het zelf uit en u krijgt een vergelijkbaar resultaat als hieronder:

Laten we dit proberen met datums:

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]

Zoals verwacht zal dit een succesvol resultaat opleveren:

Laten we het deze keer proberen met cijfers:

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]

Nog steeds een succes, toch?

Tot nu toe hebben we eenvoudige waarden gebruikt die geschikt zijn voor een redelijk vergelijkbaar type gegevens. Laten we naar het volgende niveau gaan:cijfers naar tekenreeksen.

DECLARE @number int
DECLARE @string varchar(5)

SET @number = 1701
SET @string = @number

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

Dit wordt met succes omgezet, zoals u kunt zien aan het onderstaande resultaat:

Er zijn veel meer gevallen waarin SQL Server probeert te "raden" hoe gegevens moeten worden geconverteerd. Zoals je aan deze referentie kunt zien, zijn er veel instanties in vergelijking met degenen die expliciete conversie vereisen.

Aangezien SQL Server dit toestaat, betekent dit dan dat je dit vrijelijk kunt laten gebeuren in je hele code?

Voorbehoud bij impliciete conversie

Om te beginnen kan het handig zijn. Maar zodra de limieten van elk gegevenstype zijn bereikt, zult u zich realiseren dat impliciete conversie een beetje gevaarlijk is als u dit niet aanvinkt.

Bekijk hieronder een voorbeeld:

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]

Heb je de emoji-waarde gezien? Dat telt als een Unicode-waarde.

Hoewel alle bovenstaande instructies met succes worden uitgevoerd, zijn de variabelen met niet-unicode-typen zoals varchar en char onverwachte resultaten zullen hebben. Zie het resultaat hieronder:

Toch is dat niet het enige probleem. Er verschijnen fouten wanneer de waarde buiten het bereik valt. Overweeg een voorbeeld met datums:

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]

De toewijzing van de datetime waarde voor de smalldatetime variabele zal de fout activeren zoals je hieronder kunt zien:

Maar er is nog een ander voorbehoud, waar u zich ook bewust van moet zijn als u te maken heeft met impliciete conversie:prestatieoverhead. Aangezien dit een hot topic is, verdient het een aparte sectie.

Prestatie-implicaties van verschillende SQL-gegevensconversiemethoden

Geloof het of niet, verschillende SQL-gegevensconversiemethoden zullen in werkelijke situaties verschillende prestaties leveren. En u moet zich hiervan op zijn minst bewust zijn, zodat u prestatievalkuilen kunt vermijden.

Hoe CAST(), CONVERT() en PARSE() presteren

Laten we eerst eens kijken hoe CAST (), CONVERTEREN (), en PARSE () presteren onder natuurlijke omstandigheden door te vergelijken welke sneller is. We passen het concept van ons voorbeeld aan en bewijzen het. Bekijk de onderstaande code:

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

Laten we nu eens kijken naar de code die gebruikmaakt van de AdventureWorks database van Microsoft:

  • STEL STATISTIEKEN TIJD IN geeft de CPU-tijd en de verstreken tijd weer in elk van de SELECT uitspraken
  • Vervolgens is de kolom die we kiezen om te converteren voor demonstratiedoeleinden [NationalIDNumber ], die het type nvarchar(15) . heeft .
  • De conversie is ook van een string naar een geheel getal:nvarchar(15) naar int .
  • En als laatste herstellen we de SET STATISTICS TIME naar de vorige waarde

Let op de uitvoer in de Berichten tabblad van het zoekresultaat:

Dit is wat we hebben bedacht met behulp van dit voorbeeld:

  • Het bewijst dat CAST () presteert het snelst (1 ms.) en PARSE () voert het langzaamst uit (318 ms.).
  • We volgen deze prioriteit wanneer we beslissen welke functie we moeten gebruiken om gegevens te converteren:(1 ) CAST () (2 ) CONVERTEREN () (3 ) PASEREN ().
  • Onthoud wanneer elke functie relevant is en houd rekening met de beperkingen bij het beslissen welke functie te gebruiken.

Hoe impliciete conversie presteert

Op dit punt zou je moeten kunnen zien dat ik het gebruik van functies zoals CAST() aanbeveel om gegevens te converteren. En in dit gedeelte zul je zien waarom.

Overweeg deze zoekopdracht met behulp van de WideWorldImporters database van Microsoft. Schakel het Include Actual Execution Plan in voordat u het uitvoert in SQL Server Management Studio .

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

In de bovenstaande zoekopdracht filteren we het resultaat van verkooporders met [CustomerID ] zoals '487%'. Dit is alleen om aan te tonen welk effect de impliciete conversie van een int gegevenstype heeft op varchar .

Vervolgens bekijken we het uitvoeringsplan hieronder:

Zoals je kunt zien, staat er een waarschuwing in de SELECT icoon. Beweeg daarom met uw muis om de tooltip te zien. Let vervolgens op het waarschuwingsbericht, namelijk de CONVERT_IMPLICIT .

Voordat we verder gaan, deze CONVERT_IMPLICIT waarschuwing treedt op wanneer het nodig is om een ​​impliciete conversie voor SQL Server uit te voeren. Laten we het probleem eens nader bekijken. Zoals hieronder beschreven, bestaat de waarschuwing uit 2 delen:

  • CONVERT_IMPLICIT kan van invloed zijn op "CardinalityEstimate" in de keuze van een queryplan.
  • CONVERT_IMPLICIT kan van invloed zijn op "SeekPlan" in een keuze voor een queryplan.

Beide geven aan dat uw zoekopdracht langzamer zal verlopen. Maar we weten natuurlijk waarom. We forceren opzettelijk een impliciete conversie door een LIKE . te gebruiken operator voor een geheel getal.

Wat heeft dat voor zin?

  • Impliciete conversie van gegevens zorgt ervoor dat SQL Server CONVERT_IMPLICIT gebruikt , wat de uitvoering van uw zoekopdracht vertraagt.
  • Om dit probleem op te lossen, elimineer je het gebruik van impliciete conversie. In ons geval gebruikten we [CustomerID ] LIKE '487%', we kunnen dit oplossen door [Klant-ID . te wijzigen ] =487. Als u de query corrigeert, wordt het uitvoeringsplan voor de query gewijzigd, wordt de waarschuwing eerder verwijderd en wordt de indexscan-operator gewijzigd in een indexzoekopdracht. Uiteindelijk verbeteren de prestaties.

Gelukkig einde? Ja!

Afhaalmaaltijden

Zoals aangetoond, kunnen we SQL Server niet zomaar laten converteren met een impliciete conversie. Ik raad je aan om de prioriteit te volgen als het gaat om beslissen wat je moet gebruiken bij het converteren van gegevens.

  • Ten eerste, als je gewoon wilt converteren zoals het is, gebruik dan CAST (). Het is een meer gestandaardiseerde functie bij het overzetten naar andere RDBM's.
  • Ten tweede, als je geformatteerde gegevens nodig hebt, gebruik dan CONVERT ().
  • Ten derde, als beide CAST () en CONVERTEREN () faalt om het werk te doen, gebruik PARSE ().
  • Ten slotte, om te testen op fouten bij het converteren, gebruikt u TRY_CAST (), TRY_CONVERT (), of TRY_PARSE ().

Dat was het voor nu. Ik hoop dat dit je helpt bij je volgende codeeravonturen. Breek een been!

Voor meer informatie over het onderwerp SQL-gegevensconversie van Microsoft:

  • CAST en CONVERT
  • PASEREN
  • TRY_CAST, TRY_CONVERT en TRY_PARSE

  1. Hoe kan ik MariaDB wijzigen in MySQL in XAMPP?

  2. De naam van de primaire sleutelbeperking voor meerdere tabellen in de SQL Server-database wijzigen - SQL Server / TSQL-zelfstudie, deel 64

  3. Hoe kan ik deze fout oplossen:niet-ondersteunde SQL92?

  4. Exporteer specifieke rijen uit een PostgreSQL-tabel als INSERT SQL-script