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

Concatenazione in Transact-SQL

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