Innanzitutto non puoi farne a meno, vero?
Le conversioni dei dati SQL o, più specificamente, le conversioni dei tipi di dati sono una parte essenziale del normale lavoro di programmazione di uno sviluppatore di database o di un DBA.
Ora, cosa succede se il tuo capo ha firmato un contratto con un'altra azienda per fornire loro un file in formato testo proveniente dal tuo database SQL Server?
Sembra una sfida emozionante!
Ma hai scoperto che avresti dovuto gestire una data in una stringa, un numero in una stringa e un sacco di altre conversioni di dati SQL. Sei ancora pronto per la sfida?
Non senza il tuo arsenale di trucchi per la conversione dei dati!
Cosa è disponibile fuori dagli schemi?
Quando ho iniziato a programmare T-SQL, la prima cosa che ho visto adatto allo scopo della conversione è stata CONVERT () funzione.
Inoltre, c'è la parola "convertire", giusto?
Anche se questo può essere vero, è solo uno dei 4 modi per eseguire questo lavoro. E lo stavo usando per quasi TUTTA la mia conversione di dati SQL. Sono contento di averlo superato. Perché ho imparato che i 4 metodi hanno il loro posto nel tuo codice.
Prima di arrivare all'argomento del post, vorrei presentare i 4 metodi pronti all'uso per eseguire la conversione dei dati SQL:
- CAST ()
- CONVERTI ()
- ANALISI ()
- PROVA_CAST (), TRY_CONVERT (), TRY_PARSE ()
Ciascuna delle sezioni seguenti:
- Spiega di cosa si tratta
- Indica quando usarlo (casi d'uso)
- Presenta i suoi limiti
- Fai esempi e spiegalo
Tutto ciò che viene presentato in questo articolo è il più possibile in un inglese semplice e chiaro. Quando finirai di leggere l'intero post, saprai quale metodo è appropriato per una determinata situazione.
Quindi, senza ulteriori indugi, tuffiamoci.
1. Conversione dei dati SQL mediante CAST()
Sebbene tutti i metodi che vedrai possano convertire i tipi di dati, la tua prima scelta per la conversione dovrebbe essere sicuramente CAST ().
Ecco i motivi:
- È la funzione di conversione più veloce in assoluto. Cercheremo di dimostrarlo più avanti in questo post.
- È incluso negli standard di specifica del linguaggio SQL-92. Pertanto, quando è necessario trasferire il codice su altri prodotti SQL, come MySQL, è disponibile anche la funzione.
Ecco una sintassi molto semplice per CAST ():
CAST( <expression> AS <data_type>[(length)] )
Per prima cosa, esaminiamo la sintassi:
- <espressione> è qualsiasi espressione valida che risulta in un valore che può essere convertito nel tipo di dati di destinazione.
- <tipo_dati> è il tipo di dati di destinazione.
- lunghezza è facoltativo e attiene alla dimensione dei dati.
Quando usarlo
Se l'unica cosa di cui hai bisogno è convertire un valore in un altro tipo di dati, allora CAST () è proprio ciò di cui hai bisogno.
Limitazione
Sul lato negativo, CAST () non può darti un output formattato pronto all'uso come un valore di data e ora formattato.
Esempi
A. Converti una stringa in una data:
SELECT CAST('09/11/2004 4:30PM' as datetime2)
E l'esecuzione dell'istruzione precedente risulterà in:
SELECT CAST(10.003458802 as varchar(max))
E il risultato della conversione di cui sopra è:
Ora, se hai bisogno di qualcos'altro come formattare i dati convertiti, il metodo successivo può aiutarti.
2. Conversione dei dati SQL mediante CONVERT()
La prossima opzione di conversione dei dati consiste nell'usare CONVERT (). Come ho detto prima, questo è quello che ho usato di più nei primi giorni.
Ecco la sintassi:
CONVERT( <data_type>[(length)], <expression> [, <style>])
Dalla sintassi sopra, prendi nota che lo <stile> il parametro è facoltativo. E a meno che tu non lo fornisca, la funzione sarà simile a CAST ().
È qui che è iniziata la mia confusione quando ero nuovo a SQL.
Quando usarlo
Se converti i dati con un formato istantaneo, CONVERTI () È tuo amico. Ciò significa che tratti lo <stile> parametro correttamente.
Limiti
- CAST () è più veloce di CONVERT (), quindi se hai solo bisogno di convertire i dati, usa CAST (). Se l'output deve essere formattato, utilizza CONVERT ().
- CONVERTI () non è uno standard SQL-92, quindi se hai bisogno di portarlo su altri RDBMS, evita di usarlo.
Esempi
A. Converti una data in un formato stringa aaaammgg
Nell'esempio seguente utilizzerò il database di esempio AdventureWorks e trasforma il [StartDate ] in aaaammgg :
USE AdventureWorks
GO
SELECT
[BillOfMaterialsID]
,CONVERT(varchar(10), [StartDate],112) as StartDate
FROM [Production].BillOfMaterials]
GO
Tieni presente che lo stile 112 viene utilizzato per formattare le date in aaaammgg .
Allo stesso modo, l'esempio seguente illustrerà AdventureWorks database di esempio e formatteremo il numero con virgole e con 2 cifre decimali.
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
Tieni presente che il formato 1 viene utilizzato per [Costo effettivo ]. E grazie a CONVERT (), possiamo formattare queste colonne in un istante.
Tuttavia, cosa succede se è necessario convertire un'espressione di data più lunga? CONVERTIRÀ () funziona in quel caso? Continua a leggere per conoscere il prossimo metodo.
3. Conversione dei dati SQL mediante PARSE()
Il prossimo metodo che prenderemo in considerazione è PARSE ().
Controlla la sintassi:
PARSE( <string value> AS <datatype> [USING <culture>])
Quando usarlo
- Per convertire le stringhe in date o numeri utilizzando una lingua specifica.
- Quando la stringa non può essere convertita in una data o in un numero utilizzando CAST () o CONVERTI (). Vedere gli esempi per ulteriori informazioni.
Limiti
- La conversione è possibile solo per stringhe in date e stringhe in numeri
- Si basa sulla presenza di .Net Framework Common Language Runtime (CLR) sul server.
- Non è incluso nelle specifiche standard di SQL-92, quindi il porting su altri RDBMS è un problema.
- Ha un sovraccarico delle prestazioni quando si tratta di analizzare la stringa.
Esempi
A. Conversione di una stringa di data lunga
SELECT PARSE('Monday, June 8, 2020' as datetime USING 'en-US')
L'esempio sopra è una lunga stringa di data da convertire in datetime valore usando la cultura inglese americana. Ed è qui che PARSE () farà del suo meglio.
Questo perché il codice precedente non riuscirà se utilizzi CAST () o CONVERTI ().
SELECT PARSE('€1024,01' as money using 'de-DE')
Ora, prova a eseguire la conversione utilizzando CAST () e CONVERTI ()
SELECT CONVERT(money,'€1024,01')
SELECT CAST('€1024,01' as money)
L'istruzione non genererà errori, tuttavia, dai un'occhiata a questo risultato inaspettato:
Di conseguenza, il valore è stato convertito in 102401.00 invece di 1024.01.
Finora, abbiamo scoperto che i primi 3 metodi sono soggetti a errori a meno che non li controlli. Tuttavia, il 4° metodo può essere la tua soluzione al risultato errato.
4. Conversione dei dati SQL mediante TRY_CAST(), TRY_CONVERT() o TRY_PARSE()
Infine, l'ultimo metodo per la conversione dei dati SQL utilizza una variante dei primi 3 ma con un prefisso TRY_.
Ma anche così, qual è la differenza?
Hanno gli stessi parametri dei 3 precedenti senza il prefisso TRY_. Ma la differenza è che restituiscono NULL se il valore non può essere convertito. Ora, se il valore non può essere convertito esplicitamente da nessuno dei 3, si verifica un errore. Guarda gli esempi seguenti per una migliore comprensione.
Quando usarlo
Puoi utilizzare uno qualsiasi dei 3 con istruzioni condizionali come CASE QUANDO o IIF per verificare la presenza di errori.
Limiti
I 3 hanno le stesse limitazioni di quelli senza il prefisso TRY_, ad eccezione dei valori che non possono essere convertiti.
Esempi
A. Utilizza TRY_CAST() per verificare se la conversione avrà esito positivo utilizzando IIF:
SELECT IIF(TRY_CAST('111b' AS real) IS NULL, 'Cast failed', 'Cast succeeded') AS Result
Il codice sopra restituirà "Trasmissione non riuscita" perché "111b" non può essere convertito in reale . Togli la "b" dal valore e restituirà "Cast riuscito".
SET DATEFORMAT dmy;
SELECT TRY_CONVERT(datetime2, '12/31/2010') AS Result
Questo restituirà NULL perché il formato utilizza dmy o giorno-mese-anno. E l'espressione di input per TRY_CONVERT () è nel formato mdy o mese-giorno-anno. L'errore è stato attivato perché il valore del mese è 31.
SELECT
CASE WHEN TRY_PARSE('10/21/2133' AS smalldatetime USING 'en-US') IS NULL
THEN 'True'
ELSE 'False'
END AS Result
Questo codice genererà un errore di runtime come mostrato di seguito:
Questo è tutto per i 4 metodi pronti all'uso nella conversione dei dati SQL. Ma c'è altro in arrivo.
Che ne dici della conversione dei dati SQL mediante la conversione implicita?
Consideriamo ora la conversione implicita. Questo è un metodo silenzioso.
Perché silenzioso?
Perché potresti già farlo, ma non ne sei a conoscenza. O almeno, sai che sta succedendo, ma lo stai ignorando.
In altre parole, questo è il tipo di conversione che SQL esegue automaticamente senza alcuna funzione.
Ti faccio un esempio:
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]
Il codice sopra verrà eseguito correttamente. Provalo tu stesso e otterrai un risultato simile a quello qui sotto:
Proviamo con le date:
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]
Come previsto, questo produrrà un risultato positivo:
Proviamo questa volta con i numeri:
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]
Ancora un successo, vero?
Finora, abbiamo utilizzato valori semplici che saranno adatti per un tipo di dati piuttosto simile. Entriamo nel livello successivo:dai numeri alle stringhe.
DECLARE @number int
DECLARE @string varchar(5)
SET @number = 1701
SET @string = @number
SELECT @number as [number], @string as [string]
Questo verrà convertito correttamente come puoi vedere dal risultato di seguito:
Esistono molti altri casi in cui SQL Server tenterà di "indovinare" come convertire i dati. Come puoi vedere da questo riferimento, ci sono molte istanze rispetto a quelle che richiedono una conversione esplicita.
Poiché SQL Server lo consente, significa che puoi consentire liberamente che ciò avvenga su tutto il tuo codice?
Avvertenze nella conversione implicita
Per prima cosa, può essere conveniente. Ma una volta raggiunti i limiti di ogni tipo di dati, ti renderai conto che la conversione implicita è un po' pericolosa se lasciata deselezionata.
Considera un esempio di seguito:
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]
Hai visto il valore delle emoji? Verrà conteggiato come valore unicode.
Mentre tutte le istruzioni precedenti verranno eseguite correttamente, le variabili con tipi non Unicode come varchar e carattere avrà risultati inaspettati. Vedi il risultato qui sotto:
Tuttavia, questo non è l'unico problema. Gli errori verranno visualizzati quando il valore diventa fuori intervallo. Considera un esempio con le date:
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]
L'assegnazione della data e ora valore a smalldatetime variabile attiverà l'errore come puoi vedere di seguito:
Ma c'è un altro avvertimento, di cui dovresti essere consapevole quando hai a che fare con la conversione implicita:il sovraccarico delle prestazioni. Dato che questo è un argomento caldo, merita di avere una sezione separata.
Implicazioni sulle prestazioni di diversi metodi di conversione dei dati SQL
Che ci crediate o no, diversi metodi di conversione dei dati SQL avranno prestazioni diverse nelle situazioni reali. E dovresti almeno esserne consapevole in modo da evitare trabocchetti di prestazioni.
Come si comportano CAST(), CONVERT() e PARSE()
Per prima cosa, esaminiamo come CAST (), CONVERTI () e ANALISI () eseguire in condizioni naturali confrontando quale è più veloce. Adattiamo e dimostriamo il concetto del nostro esempio tratto da qui. Considera il codice seguente:
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
Ora esaminiamo il codice che utilizza AdventureWorks database di Microsoft:
- ATTIVARE L'ORA DELLE STATISTICHE emetterà il tempo della CPU e il tempo trascorso in ciascuno dei SELECT dichiarazioni
- Quindi, la colonna che scegliamo di convertire a scopo dimostrativo è [NationalIDNumber ], che ha un tipo di nvarchar(15) .
- Inoltre, la conversione è da una stringa a un numero intero:nvarchar(15) a int .
- E infine, ripristiniamo il TEMPO IMPOSTATO PER LE STATISTICHE al suo valore precedente
Nota l'output nei Messaggi scheda del risultato della query:
Ecco cosa abbiamo ottenuto utilizzando questo esempio:
- Dimostra che CAST () esegue il più veloce (1 ms.) e PARSE () esegue il più lento (318 ms.).
- Seguiamo questa precedenza quando decidiamo quale funzione utilizzare per convertire i dati:(1 ) CAST () (2 ) CONVERTI () (3 ) ANALISI ().
- Ricorda quando ogni funzione è rilevante e considera i limiti quando decidi quale funzione utilizzare.
Come funziona la conversione implicita
A questo punto, dovresti essere in grado di vedere che consiglio l'uso di funzioni come CAST() per convertire i dati. E in questa sezione vedrai perché.
Considera questa query utilizzando WideWorldImporters database di Microsoft. Prima di eseguirlo, abilita Includi piano di esecuzione effettivo in SQL Server Management Studio .
USE WideWorldImporters
GO
SELECT
[CustomerID]
,[OrderID]
,[OrderDate]
,[ExpectedDeliveryDate]
FROM [Sales].[Orders]
WHERE [CustomerID] like '487%'
Nella query precedente, filtriamo il risultato degli ordini di vendita con [CustomerID ] come "487%". Questo è solo per dimostrare quale effetto ha la conversione implicita di un int tipo di dati ha su varchar .
Successivamente, esaminiamo il piano di esecuzione di seguito:
Come puoi vedere, c'è un avviso in SELECT icona. Pertanto, passa il mouse con il mouse per vedere il suggerimento. Quindi, nota il messaggio di avviso, ovvero CONVERT_IMPLICIT .
Prima di continuare, questo CONVERT_IMPLICIT avviso si verifica quando è necessario eseguire una conversione implicita per SQL Server. Diamo un'occhiata più da vicino al problema. Come descritto di seguito, l'avviso è composto da 2 parti:
- CONVERTI_IMPLICIT può influire su "CardinalityEstimate" nella scelta di un piano di query.
- CONVERTI_IMPLICIT può influire su "SeekPlan" nella scelta di un piano di query.
Entrambi indicano che la tua query verrà eseguita più lentamente. Ma sappiamo perché, ovviamente. Forziamo intenzionalmente una conversione implicita utilizzando un MI PIACE operatore per un valore intero.
Che senso ha?
- La conversione implicita dei dati fa sì che SQL Server utilizzi CONVERT_IMPLICIT , che rallenta l'esecuzione della query.
- Per risolvere questo problema, elimina l'uso della conversione implicita. Nel nostro caso, abbiamo utilizzato [CustomerID ] MI PIACE "487%", possiamo risolverlo modificando [ID cliente ] =487. La correzione della query cambierà il piano di esecuzione della query, rimuoverà l'avviso in precedenza e cambierà l'operatore di scansione dell'indice in una ricerca dell'indice. Alla fine, le prestazioni migliorano.
Lieto fine? Sì!
Da asporto
Come mostrato, non possiamo semplicemente lasciare che SQL Server esegua la conversione con una conversione implicita. Ti consiglio di seguire la precedenza quando si tratta di decidere cosa utilizzare durante la conversione dei dati.
- In primo luogo, se devi solo convertire così com'è, usa CAST (). È una funzione più standardizzata quando è interessato il porting su altri RDBM.
- In secondo luogo, se hai bisogno di dati formattati, usa CONVERT ().
- In terzo luogo, se entrambi CAST () e CONVERTI () non riesce a fare il lavoro, usa PARSE ().
- Infine, per verificare la presenza di errori durante la conversione, utilizza TRY_CAST (), TRY_CONVERT () o TRY_PARSE ().
Bene, per ora questo è tutto. Spero che questo ti aiuti con le tue prossime avventure di programmazione. Rompi una gamba!
Per saperne di più sull'argomento della conversione dei dati SQL da Microsoft:
- CAST e CONVERTI
- Analizza
- TRY_CAST, TRY_CONVERT e TRY_PARSE