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