Inleiding
Ervan uitgaande dat u een tabel bijhoudt met klantgegevens en uw baas u vraagt om hem de huidige lijst met klanten en hun telefoonnummers te sturen. Normaal gesproken extraheer je de gegevens en stuur je hem een spreadsheet met rijen en kolommen. Je kunt er ook voor kiezen om een beetje stijlvol te zijn en hem de benodigde informatie in een meer mensvriendelijk formaat te sturen. SQL Server biedt functies waarmee we dit kunnen bereiken door Engelse uitdrukkingen te combineren met gegevens in tabellen om een uitvoer te presenteren die voor niet-technische mensen gemakkelijker te lezen is. Deze functies kunnen ook subtieler worden gebruikt.
De CONCAT-functie
De functie CONCAT accepteert twee of meer tekenreeksargumenten en retourneert de combinatie van dergelijke tekenreeksen als een enkele uitdrukking. Dit kan handig zijn als u de inhoud van verschillende kolommen als een enkele uitdrukking wilt weergeven. Een eenvoudig voorbeeld van het gebruik van deze functie wordt getoond in Listing 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
Let op de variaties van deze verklaring met behulp van de spatie en de resultaten in Fig. 1.
Afb. 1. Eenvoudige CONCAT-verklaring
Als we de CONCAT-instructie proberen te gebruiken met een invoerwaarde van het gegevenstype INT, voert SQL Server een impliciete conversie uit en retourneert nog steeds een string-uitvoer zoals weergegeven in figuur 2. We kunnen bevestigen dat dit is wat er werkelijk gebeurt door diep in de details van de verklaring in Listing 2. Kijk eerst eens naar de structuur van de tabel waarin we geïnteresseerd zijn. Fig 2 laat ons zien dat het PhoneNumber# en FirstTranDate kolommen zijn respectievelijk BIGINT- en DATETIME-kolommen.
Afb. 2. Structuur van de klantentabel
-- Listing 2: Implicit Conversion When using CONCAT (BIGINT) USE EXAM GO SELECT CONCAT(firstname , ' ' ,lastname , '''s ' , 'Phone number is ' ,phonenumber1) FROM CUSTOMER;
Een snelle blik op het uitvoeringsplan leert ons dat SQL Server een impliciete conversie uitvoert in de kolom Telefoonnummer1. Dit zal hetzelfde zijn als de kolom het datumgegevenstype was zoals weergegeven in Listing 4 en Fig. 4. De CONCAT-functie voert een impliciete conversie uit op basis van de regels die worden beschreven in de grafiek in Fig. 6.
Afb. 3. Impliciete conversie van BIGINT-gegevenstype naar 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;
Afb. 4. Impliciete conversie van DATETIME gegevenstype naar VARCHAR
Afb. 5. Impliciete conversie van BIGINT-gegevenstype naar VARCHAR
Afb. 6. Conversie van gegevenstype in SQL Server
De primaire use case voor deze functie kan worden afgeleid uit de bovenstaande demonstraties. Een voorbeeld is een geval waarin bepaalde informatie op een dashboard of webpagina in gebruiksvriendelijkere taal moet worden weergegeven met behulp van gegevens uit een aantal kolommen of zelfs afzonderlijke tabellen.
De CONCAT_WS-functie
De CONCAT_WS-functie is een uitbreiding van de CONCAT-functie. Hiermee kunnen we een gewenst scheidingsteken opgeven als de eerste parameter. Listing 4 toont ons een wijziging van een van de uitspraken die we eerder in Listing 1 gebruikten.
--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;
Merk op dat CONCAT_WS het eenvoudiger maakt om een statement te maken met een spatie als scheidingsteken in vergelijking met het invoeren van een spatie als argument na elk argument.
--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;
Aaneenschakeling met het "+"-teken
SQL Server ondersteunt het gebruik van het "+"-teken om op een veel eenvoudigere manier te bereiken wat de CONCAT-functie doet. Deze benadering wordt meestal gebruikt om T-SQL-instructies te genereren wanneer u bewerkingen op een groot aantal objecten moet uitvoeren. Lijst 7 laat zien hoe we een statistische update-batch kunnen genereren voor alle tabellen in de examendatabase.
-- 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
Let op de vierkante haken in de tweede verklaring. Het is handig bij het omgaan met een systeemobject met spaties of speciale tekens.
-- 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
Zodra de uitvoer is gegenereerd, kan deze worden gebruikt om gebruikers aan te maken in elke gewenste database, zoals weergegeven in Listing 7. Merk op dat we een filter hebben toegevoegd voor de inlognamen waarin we geïnteresseerd zijn. Deze aanpak kan worden gebruikt om allerlei soorten verklaringen te genereren en roepen dergelijke verklaringen binnen dezelfde sessie. Een complexer voorbeeld zijn de volgende instructies die op creatieve wijze alle indexen in elke database opnieuw opbouwen. (Zie Lijsten 8 en 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
De query in Listing 10 laat zien hoe we strings kunnen combineren met datums die expliciet zijn geconverteerd naar strings. De Aaneenschakeling van tekenreeksen wordt gebruikt om een algemene back-uppadvariabele te genereren die later wordt gebruikt binnen de functie 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'
Conclusie
In dit artikel hebben we een aantal manieren laten zien om aaneenschakeling in SQL Server te gebruiken. We hebben voorbeelden gegeven van de CONCAT-functie, de CONCAT_WS-functie en het gebruik van het “+”-teken. Alle drie de methoden kunnen erg handig zijn bij het genereren van uitspraken door waarden uit verschillende kolommen te combineren of om eenvoudig informatie weer te geven in een gewenst, mensvriendelijk formaat. Microsoft-documentatie bevat meer informatie over de syntaxis en mogelijkheden van deze functies.
Referenties
Casten en converteren (Transact-SQL)
Concat Transact-SQL
Concat_ws Transact-SQL
String aaneenschakeling