Introduzione
Supponendo che tu mantenga una tabella contenente i dati dei clienti e che il tuo capo ti chieda di inviargli l'elenco corrente dei clienti e i loro numeri di telefono. In genere estrai i dati e gli invii un foglio di calcolo con righe e colonne. Potresti anche decidere di essere un po' alla moda e inviargli le informazioni richieste in un formato più adatto alle persone. SQL Server fornisce funzioni che ci consentono di ottenere questo risultato combinando le espressioni inglesi con i dati all'interno delle tabelle per presentare un output che è più facile da leggere per le persone non tecniche. Queste funzioni possono anche essere utilizzate per usi più sottili.
La funzione CONCAT
La funzione CONCAT accetta due o più argomenti di stringa e restituisce la combinazione di tali stringhe come un'unica espressione. Questo può essere utile se si desidera visualizzare il contenuto di colonne diverse come un'unica espressione. Un semplice esempio di utilizzo di questa funzione è mostrato nel Listato 1.
-- Listing 1: Simple CONCAT Statement select CONCAT('This','Function','joins','strings.') as statement1; select CONCAT('This ','Function ','joins ','strings.') as statement2; select CONCAT('This',' ','Function',' ','joins',' ','strings') as statement
Nota le variazioni di questa affermazione usando lo spazio ei risultati in Fig. 1.
Fig. 1. Semplice dichiarazione CONCAT
Se proviamo a utilizzare l'istruzione CONCAT con un valore di input del tipo di dati INT, SQL Server esegue una conversione implicita e restituisce comunque un output di stringa come mostrato in Fig 2. Possiamo confermare che questo è ciò che sta effettivamente accadendo scavando in profondità nel dettagli della dichiarazione nel Listato 2. Prima di tutto, dai un'occhiata alla struttura della tabella che ci interessa. La Fig 2 ci mostra che il PhoneNumber# e FirstTranDate le colonne sono rispettivamente BIGINT e DATETIME.
Fig. 2. Struttura della Tabella Clienti
-- Listing 2: Implicit Conversion When using CONCAT (BIGINT) USE EXAM GO SELECT CONCAT(firstname , ' ' ,lastname , '''s ' , 'Phone number is ' ,phonenumber1) FROM CUSTOMER;
Una rapida occhiata al piano di esecuzione mostra che SQL Server esegue una conversione implicita nella colonna PhoneNumber1. Questo sarà lo stesso se la colonna fosse il tipo di dati data come mostrato nel Listato 4 e Fig. 4. La funzione CONCAT esegue la conversione implicita in base alle regole delineate nel grafico mostrato in Fig. 6.
Fig. 3. Conversione implicita del tipo di dati BIGINT in VARCHAR
-- Listing 3: Implicit Conversion When using CONCAT (DATETIME) USE EXAM GO SELECT FirstTranDate, CONCAT(FirstName , ' ' ,LastName , '''s ' , 'first transaction date is ' ,FirstTranDate) as STMT FROM CUSTOMER;
Fig. 4. Conversione implicita di DATETIME tipo di dati su VARCHAR
Fig. 5. Conversione implicita del tipo di dati BIGINT in VARCHAR
Fig. 6. Conversione del tipo di dati in SQL Server
Il caso d'uso principale per questa funzione può essere dedotto dalle dimostrazioni precedenti. Un esempio potrebbe essere un caso in cui alcune informazioni devono essere visualizzate su una dashboard o una pagina Web in un linguaggio più intuitivo utilizzando i dati di un numero di colonne o persino di tabelle separate.
La funzione CONCAT_WS
La funzione CONCAT_WS è un'estensione della funzione CONCAT. Ci consente di specificare un separatore desiderato come primo parametro. Il Listato 4 ci mostra una modifica di una delle affermazioni che abbiamo usato in precedenza nel Listato 1.
--Listing 4 Using CONCAT_WS SELECT CONCAT('This',' ','Function',' ','joins',' ','strings') AS statement; SELECT CONCAT('This',' ','Function',' ','joins',' ','strings') AS statement; SELECT CONCAT_WS(' ','This','Function','joins','strings') AS statement;
Si noti che CONCAT_WS semplifica la costruzione di un'istruzione con lo spazio come separatore rispetto all'introduzione di uno spazio come argomento dopo ogni argomento.
--Listing 5 Using CONCAT_WS with Columns USE EXAM GO SELECT CONCAT(firstname , ' ' ,lastname , '''s ' , 'Phone number is ' ,phonenumber1) FROM CUSTOMER; USE EXAM GO SELECT CONCAT_WS(' ',firstname ,lastname , '''s ' , 'Phone number is' ,phonenumber1) FROM CUSTOMER;
Concatenazione con il segno "+"
SQL Server supporta l'uso del segno "+" per ottenere ciò che fa la funzione CONCAT in un modo molto più semplice. Questo approccio viene in genere utilizzato per generare istruzioni T-SQL quando è necessario eseguire operazioni su un numero elevato di oggetti. Il Listato 7 mostra come possiamo generare un batch di aggiornamento delle statistiche per tutte le tabelle nel database degli esami.
-- Listing 6 Generating Update Stats Statements USE Exam GO SELECT 'UPDATE STATISTICS ' + name + ' WITH SAMPLE 25 PERCENT;' as STMT from sys.tables ; SELECT 'UPDATE STATISTICS [' + name + '] WITH SAMPLE 25 PERCENT;' as STMT from sys.tables ; GO
Notare le parentesi quadre nella seconda affermazione. È utile quando si ha a che fare con un oggetto di sistema con spazi o caratteri speciali.
-- Listing 7 Generating Create User Statements USE MASTER GO SELECT 'CREATE USER [' + LOGINNAME + '] FOR LOGIN [' + LOGINNAME + '] ;' AS STMT FROM SYSLOGINS WHERE LOGINNAME NOT LIKE '#%'; GO USE EXAM GO CREATE USER [sa] FOR LOGIN [sa] ; CREATE USER [EPG-KIGIRI\ekocauris] FOR LOGIN [EPG-KIGIRI\ekocauris] ; CREATE USER [KAIROSAFRIKA\kigiri] FOR LOGIN [KAIROSAFRIKA\kigiri] ; CREATE USER [NT SERVICE\SQLWriter] FOR LOGIN [NT SERVICE\SQLWriter] ; CREATE USER [NT SERVICE\Winmgmt] FOR LOGIN [NT SERVICE\Winmgmt] ; CREATE USER [NT Service\MSSQL$I2019] FOR LOGIN [NT Service\MSSQL$I2019] ; CREATE USER [NT AUTHORITY\SYSTEM] FOR LOGIN [NT AUTHORITY\SYSTEM] ; CREATE USER [NT SERVICE\SQLAgent$I2019] FOR LOGIN [NT SERVICE\SQLAgent$I2019] ; CREATE USER [NT SERVICE\SQLTELEMETRY$I2019] FOR LOGIN [NT SERVICE\SQLTELEMETRY$I2019] ; CREATE USER [KAIROSAFRIKA\sberko] FOR LOGIN [KAIROSAFRIKA\sberko] ; GO
Una volta generato, l'output può essere utilizzato per creare utenti in qualsiasi database desiderato, come mostrato nel Listato 7. Nota che abbiamo aggiunto un filtro per i nomi di accesso che ci interessano. Questo approccio può essere utilizzato per generare tutti i tipi di istruzioni e chiamare tali dichiarazioni all'interno della stessa sessione. Un esempio più complesso sono le seguenti istruzioni che ricostruiscono in modo creativo tutti gli indici in qualsiasi database. (Vedi elenchi 8 e 9).
--Listing 8 Generating Index Rebuild Statements USE EXAM GO CREATE TABLE #INDTAB (ID SMALLINT IDENTITY(1,1), REBUILDSTMT NVARCHAR(600)) INSERT INTO #INDTAB SELECT 'SET QUOTED_IDENTIFIER ON; ALTER INDEX [' + B.NAME + '] ON [' + SCHEMA_NAME(C.SCHEMA_ID) + '].[' + OBJECT_NAME(A.OBJECT_ID) + '] REBUILD WITH (ONLINE = OFF ,FILLFACTOR=80 ,SORT_IN_TEMPDB=ON ,PAD_INDEX = ON , STATISTICS_NORECOMPUTE = OFF);' --INTO #INDTAB FROM SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(), NULL, NULL, NULL, NULL) AS A JOIN SYS.INDEXES AS B JOIN SYS.OBJECTS AS C ON B.OBJECT_ID = C.OBJECT_ID ON A.OBJECT_ID = B.OBJECT_ID AND A.INDEX_ID = B.INDEX_ID WHERE AVG_FRAGMENTATION_IN_PERCENT > 30 ; SELECT * FROM #INDTAB; GO DROP TABLE #INDTAB; GO --Listing 9 Generating and Executing Index Rebuild Statements USE EXAM GO CREATE TABLE #INDTAB (ID SMALLINT IDENTITY(1,1), REBUILDSTMT NVARCHAR(600)) INSERT INTO #INDTAB SELECT 'SET QUOTED_IDENTIFIER ON; ALTER INDEX [' + B.NAME + '] ON [' + SCHEMA_NAME(C.SCHEMA_ID) + '].[' + OBJECT_NAME(A.OBJECT_ID) + '] REBUILD WITH (ONLINE = OFF ,FILLFACTOR=80 ,SORT_IN_TEMPDB=ON ,PAD_INDEX = ON , STATISTICS_NORECOMPUTE = OFF);' --INTO #INDTAB FROM SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(), NULL, NULL, NULL, NULL) AS A JOIN SYS.INDEXES AS B JOIN SYS.OBJECTS AS C ON B.OBJECT_ID = C.OBJECT_ID ON A.OBJECT_ID = B.OBJECT_ID AND A.INDEX_ID = B.INDEX_ID WHERE AVG_FRAGMENTATION_IN_PERCENT > 30 ; GO DECLARE @SQL NVARCHAR(4000); SELECT @SQL= REBUILDSTMT FROM #INDTAB ; PRINT @SQL EXEC SP_EXECUTESQL @SQL; GO DROP TABLE #INDTAB; GO
La query nel Listato 10 mostra come possiamo combinare stringhe con date convertite in modo esplicito in stringhe. La concatenazione di stringhe viene utilizzato per generare una variabile di percorso di backup comune che verrà successivamente utilizzata all'interno della funzione SP_MSFOREACHDB.
--Listing 10 Generating a Common Backup Path EXEC SP_MSFOREACHDB @COMMAND1=' DECLARE @BACKUP SYSNAME SET @BACKUP=N''G:\BACKUP\?''+CONVERT(NVARCHAR,GETDATE(),112)+N''.BAK'' USE [?] IF ''?'' NOT IN ("MODEL","TEMPDB") BEGIN BACKUP DATABASE ? TO DISK = @BACKUP WITH INIT , NOUNLOAD , COMPRESSION, NAME = N''?'', NOSKIP , NOFORMAT END'
Conclusione
In questo articolo abbiamo mostrato alcuni modi per usare la concatenazione in SQL Server. Abbiamo fornito esempi della funzione CONCAT, della funzione CONCAT_WS e dell'uso del segno “+”. Tutti e tre i metodi possono essere molto utili nella generazione di istruzioni combinando valori di colonne diverse o semplicemente per visualizzare le informazioni in un formato adatto alle persone. La documentazione Microsoft contiene ulteriori informazioni sulla sintassi e sulle capacità di queste funzioni.
Riferimenti
Trasmetti e converti (Transact-SQL)
Concat Transact-SQL
Concat_ws Transact-SQL
Concatenazione di stringhe