sql >> Base de Datos >  >> RDS >> Database

Concatenación en Transact-SQL

Introducción

Supongamos que mantiene una tabla que contiene datos de clientes y su jefe le pide que le envíe la lista actual de clientes y sus números de teléfono. Por lo general, extraería los datos y le enviaría una hoja de cálculo con filas y columnas. También podría decidir ser un poco elegante y enviarle la información requerida en un formato más amigable para las personas. SQL Server proporciona funciones que nos permiten lograr esto al combinar expresiones en inglés con datos dentro de tablas para presentar una salida que es más fácil de leer para personas sin conocimientos técnicos. Estas funciones también se pueden utilizar para usos más sutiles.

La función CONCAT

La función CONCAT acepta dos o más argumentos de cadena y devuelve la combinación de dichas cadenas como una sola expresión. Esto puede ser útil si desea mostrar el contenido de diferentes columnas como una sola expresión. Un ejemplo simple del uso de esta función se muestra en el Listado 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

Note las variaciones de esta declaración usando el espacio y los resultados en la Fig. 1.

fig. 1. Declaración CONCAT simple

Si tratamos de usar la declaración CONCAT con un valor de entrada de tipo de datos INT, SQL Server realiza una conversión implícita y aún devuelve una salida de cadena como se muestra en la figura 2. Podemos confirmar que esto es lo que realmente está sucediendo al profundizar en el detalles de la instrucción en el Listado 2. En primer lugar, eche un vistazo a la estructura de la tabla que nos interesa. La figura 2 nos muestra que el PhoneNumber# y FirstTranDate las columnas son columnas BIGINT y DATETIME respectivamente.

fig. 2. Estructura de la Tabla de Clientes

-- Listing 2: Implicit Conversion When using CONCAT (BIGINT)
USE EXAM
GO
SELECT CONCAT(firstname
, ' '
,lastname
, '''s '
, 'Phone number is '
,phonenumber1) 
FROM CUSTOMER;

Echar un vistazo rápido al plan de ejecución nos muestra que SQL Server realiza una conversión implícita en la columna PhoneNumber1. Será lo mismo si la columna fuera del tipo de datos de fecha, como se muestra en el Listado 4 y la Fig. 4. La función CONCAT realiza una conversión implícita según las reglas descritas en el gráfico que se muestra en la Fig. 6.

fig. 3. Conversión implícita del tipo de datos BIGINT a 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. Conversión implícita de DATETIME tipo de datos a VARCHAR

fig. 5. Conversión implícita del tipo de datos BIGINT a VARCHAR

fig. 6. Conversión de tipos de datos en SQL Server

El caso de uso principal para esta función se puede deducir de las demostraciones anteriores. Un ejemplo sería un caso en el que cierta información debe mostrarse en un tablero o página web en un lenguaje más amigable utilizando datos de varias columnas o incluso tablas separadas.

La función CONCAT_WS

La función CONCAT_WS es una extensión de la función CONCAT. Nos permite especificar un separador deseado como primer parámetro. El Listado 4 nos muestra una modificación de una de las declaraciones que usamos previamente en el Listado 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;

Tenga en cuenta que CONCAT_WS simplifica la construcción de una declaración con un espacio como separador en comparación con la introducción de un espacio como argumento después de cada argumento.

--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;

Concatenación con el signo “+”

SQL Server admite el uso del signo "+" para lograr lo que hace la función CONCAT de una manera mucho más simple. Este enfoque generalmente se usa para generar declaraciones T-SQL cuando necesita realizar operaciones en una gran cantidad de objetos. El Listado 7 muestra cómo podemos generar un lote de actualización de estadísticas para todas las tablas en la base de datos del examen.

-- 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

Observe los corchetes en la segunda declaración. Es útil cuando se trata de un objeto del sistema con espacios o caracteres especiales.

-- 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 vez que se genera la salida, se puede usar para crear usuarios en cualquier base de datos deseada, como se muestra en el Listado 7. Tenga en cuenta que hemos agregado un filtro para los nombres de inicio de sesión que nos interesan. Este enfoque se puede usar para generar todo tipo de declaraciones. y llame a tales declaraciones dentro de la misma sesión. Un ejemplo más complejo son las siguientes declaraciones que reconstruyen creativamente todos los índices en cualquier base de datos. (Consulte los Listados 8 y 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 consulta del Listado 10 muestra cómo podemos combinar cadenas con fechas explícitamente convertidas en cadenas. La Concatenación de cadenas se usa para generar una variable de ruta de respaldo común que luego se usa dentro de la función 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'

Conclusión

En este artículo, hemos mostrado algunas formas de usar la concatenación en SQL Server. Hemos dado ejemplos de la función CONCAT, la función CONCAT_WS y el uso del signo "+". Los tres métodos pueden ser muy útiles para generar declaraciones mediante la combinación de valores de diferentes columnas o simplemente para mostrar información en un formato amigable para las personas deseado. La documentación de Microsoft tiene más información sobre la sintaxis y las capacidades de estas funciones.

Referencias

Transmitir y convertir (Transact-SQL)

Concat Transact-SQL

Concat_ws Transact-SQL

Concatenación de cadenas