Въведение
Ако приемем, че поддържате таблица, съдържаща клиентски данни, и вашият шеф ви моли да му изпратите текущия списък с клиенти и техните телефонни номера. Обикновено извличате данните и му изпращате електронна таблица с редове и колони. Можете също така да решите да бъдете малко стилни и да му изпратите необходимата информация в по-удобен за хората формат. SQL Server предоставя функции, които ни позволяват да постигнем това чрез комбиниране на английски изрази с данни в таблици, за да представим изход, който е по-лесен за четене от нетехнически хора. Тези функции могат да бъдат използвани и за по-фини приложения.
Функцията CONCAT
Функцията CONCAT приема два или повече аргумента на низове и връща комбинацията от такива низове като един израз. Това може да бъде полезно, ако искате да покажете съдържанието на различни колони като един израз. Прост пример за използване на тази функция е показан в листинг 1.
-- Листинг 1:Прости CONCAT изрази изберете CONCAT('This','Function','joins','strings.') като изявление1;изберете CONCAT('This','Function','joins','strings.'). .') като изявление2;изберете CONCAT('Това',' ','Функция',' ','съединява',' ','низове') като изявление
Забележете вариациите на това твърдение, като използвате интервала и резултатите от фиг. 1.
Фиг. 1. Проста декларация CONCAT
Ако се опитаме да използваме израза CONCAT с входна стойност от тип данни INT, SQL Server прави имплицитно преобразуване и все пак връща изходен низ, както е показано на Фигура 2. Можем да потвърдим, че това всъщност се случва, като копаем дълбоко в подробности за израза в листинг 2. Първо, разгледайте структурата на таблицата, която ни интересува. Фигура 2 ни показва, че PhoneNumber# и FirstTranDate колоните са съответно BIGINT и DATETIME.
Фиг. 2. Структура на таблицата с клиенти
-- Списък 2:Неявно преобразуване при използване на CONCAT (BIGINT) ИЗПОЛЗВАЙТЕ EXAMGOSELECT CONCAT(собствено име, ' ', фамилия, '''s ', 'Телефонен номер е ',телефонен номер1) ОТ КЛИЕНТА;
Бърз поглед върху плана за изпълнение ни показва, че SQL Server извършва неявно преобразуване в колоната PhoneNumber1. Това ще бъде същото, ако колоната е тип данни за дата, както е показано в листинг 4 и фиг. 4. Функцията CONCAT извършва имплицитно преобразуване въз основа на правилата, очертани в диаграмата, показана на фиг. 6.
Фиг. 3. Неявно преобразуване на типа данни BIGINT в VARCHAR
-- Листинг 3:Неявно преобразуване при използване на CONCAT (DATETIME) ИЗПОЛЗВАЙТЕ EXAMGOSELECT FirstTranDate, CONCAT(FirstName, ' ',LastName, '''s ', 'датата на първата транзакция е ',FirstTranDate) като STMTFROM КЛИЕНТ;предварително>
Фиг. 4. Неявно преобразуване на DATETIME тип данни към VARCHAR
Фиг. 5. Неявно преобразуване на типа данни BIGINT в VARCHAR
Фиг. 6. Преобразуване на тип данни в SQL Server
Основният случай на използване на тази функция може да бъде изведен от демонстрациите по-горе. Пример би бил случай, при който някаква информация трябва да бъде показана на табло за управление или уеб страница на по-приятелски език, като се използват данни от редица колони или дори отделни таблици.
Функцията CONCAT_WS
Функцията CONCAT_WS е разширение на функцията CONCAT. Позволява ни да посочим желания разделител като първи параметър. Списък 4 ни показва модификация на едно от изразите, които използвахме преди в листинг 1.
--Списък 4 Използване на CONCAT_WSSELECT CONCAT('Това',' ','Функция',' ','присъединява',' ','низове') AS израз;SELECT CONCAT('Това',',',' Function',' ','joins',' ','strings') AS изявление;SELECT CONCAT_WS(' ','This','Function','joins','strings') AS изявление;Забележете, че CONCAT_WS улеснява конструирането на израз с интервал като разделител в сравнение с въвеждането на интервал като аргумент след всеки аргумент.
--Списък 5 Използване на CONCAT_WS с ColumnsUSE EXAMGOSELECT CONCAT(собствено име, ' ',фамилно име, '''s ', 'Телефонният номер е ',телефонен номер1) ОТ КЛИЕНТА; ИЗПОЛЗВАЙТЕ EXAMGOSELECT CONCAT_WS(' ',firstname', ''s ', 'Телефонният номер е',phonenumber1) ОТ КЛИЕНТА;Свързване със знака „+“
SQL Server поддържа използването на знака „+“ за постигане на това, което прави функцията CONCAT по много по-опростен начин. Този подход обикновено се използва за генериране на T-SQL изрази, когато трябва да извършите операции върху голям брой обекти. Списък 7 показва как можем да генерираме пакет за актуализиране на статистиката за всички таблици в базата данни за изпитите.
-- Листинг 6 Генериране на изявления за актуализиране на статистически данниUSE ExamGOSELECT 'АКТУАЛИЗИРАНЕ НА СТАТИСТИКА ' + име + ' С ПРОБА 25 ПРОЦЕНТА;' като STMT от sys.tables;ИЗБЕРЕТЕ 'АКТУАЛИЗИРАНЕ НА СТАТИСТИКАТА [' + име + '] С ПРОБА 25 ПРОЦЕНТА;' като STMT от sys.tables;GOОбърнете внимание на квадратните скоби във второто твърдение. Полезно е, когато работите със системен обект с интервали или специални знаци.
-- Листинг 7 Генериране Създаване на потребителски изявленияUSE MASTERGOSELECT 'CREATE USER [' + LOGINNAME + '] FOR LOGIN [' + LOGINNAME + '];' КАТО STMT ОТ SYSLOGINSWHERE LOGINNAME НЕ КАТО '#%';GOUSE EXAMGOCREATE USER [sa] FOR LOGIN [sa];СЪЗДАДЕТЕ ПОТРЕБИТЕЛ [EPG-KIGIRI\ekocauris] ЗА ВХОД [EPG-KIGIRI\ekocauris];KAIROSARIUSER\kigiFRIKA ЗА ВХОД [KAIROSAFRIKA\kigiri];СЪЗДАЙТЕ ПОТРЕБИТЕЛ [NT SERVICE\SQLWriter] ЗА ВХОД [NT SERVICE\SQLWriter];СЪЗДАЙТЕ ПОТРЕБИТЕЛ [NT SERVICE\Winmgmt] ЗА ВХОД [NT SERVICE\Winmgmt] [LNTRE Service\LNTRE Service I2019] ЗА ВХОД [NT Service\MSSQL$I2019];СЪЗДАЙТЕ ПОТРЕБИТЕЛ [NT AUTHORITY\SYSTEM] ЗА ВХОД [NT AUTHORITY\SYSTEM];СЪЗДАЙТЕ ПОТРЕБИТЕЛ [NT SERVICE\SQLAgent$I2019] ЗА ВХОД [NT AUTHORITY\SYSTEM] ЗА ВХОД [NT AUTHORITY\SYSTEM];СЪЗДАЙТЕ ПОТРЕБИТЕЛ [NT SERVICE\SQLAgent$I2019] ЗА ВХОД [NT AUTHORITY\SYSTEM];СЪЗДАДЕТЕ ПОТРЕБИТЕЛ [NT SERVICE\SQLTELEMETRY$I2019] ЗА ВХОД [NT SERVICE\SQLTELEMETRY$I2019];СЪЗДАДЕТЕ ПОТРЕБИТЕЛ [KAIROSAFRIKA\sberko] ЗА ВХОД [KAIROSAFRIKA\sberko];GOСлед като изходът е генериран, той може да се използва за създаване на потребители във всяка желана база данни, както е показано в листинг 7. Имайте предвид, че сме добавили филтър за имената за вход, които ни интересуват. Този подход може да се използва за генериране на всякакви изрази и извикайте такива изявления в рамките на същата сесия. По-сложен пример са следните твърдения, които творчески възстановяват всички индекси във всяка база данни. (Вижте листинги 8 и 9).
--Списък 8 Генериране на инструкции за възстановяване на индекс ИЗПОЛЗВАЙТЕ EXAMGOCREATE TABLE #INDTAB (ID SMALLINT IDENTITY(1,1), REBUILDSTMT NVARCHAR(600))INSERT INTO #INDTAB SELECT 'SET QUOTED_IDENTIFIER ON [' + BINDNAME] '] ON [' + SCHEMA_NAME(C.SCHEMA_ID) + '].[' + OBJECT_NAME(A.OBJECT_ID) + '] ПОВТОРНО ИЗГРАЖДАНЕ С (ONLINE =OFF, FILLFACTOR=80, SORT_IN_TEMPDB=ON, PAD_INDEX =ON, STATISTICS_NO OFF, STATISTICS_ONLINE );'--INTO #INDTABFROM SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(), NULL, NULL, NULL, NULL) КАТО ПРИСЪЕДИНЕТЕ SYS.INDEXES КАТО B ПРИСЪЕДИНЕТЕ SYS.OBJECTS КАТО CON B.OBJECT_ID =C.OBJECT_CTON A.OBJECT_IDON .OBJECT_ID И A.INDEX_ID =B.INDEX_ID КЪДЕТО AVG_FRAGMENTATION_IN_PERCENT> 30;SELECT * ОТ #INDTAB;GODROP TABLE #INDTAB;GO--листинг 9 Генериране и изпълнение на инструкции за възстановяване на индексUSE TABENTITYLESMALLINTAB (EXAMENTLESMALLINTAB) , 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_NAME(A.OBJECT_NAME) _ID) + '] ПОВТОРНО СЪС (ONLINE =OFF,FILLFACTOR=80,SORT_IN_TEMPDB=ON,PAD_INDEX =ON, STATISTICS_NORECOMPUTE =OFF);'--INTO #INDTABFROM SYS.DM_DB_INDEX_PHYSICAL_STATS, NULLNULLDB_STATS, ) КАТО ПРИСЪЕДИНЕТЕ SYS.INDEXES КАТО B ПРИСЪЕДИНЕТЕ SYS.OBJECTS КАТО CON B.OBJECT_ID =C.OBJECT_IDON A.OBJECT_ID =B.OBJECT_ID И A.INDEX_ID =B.INDEX_ID WHERE AVG_FRAGMENTATION_IN_PERCGENTQOD> 300 ); ИЗБЕРЕТЕ @SQL=REBUILDSTMT ОТ #INDTAB;ПЕЧАТ @SQLEXEC SP_EXECUTESQL @SQL;GODROP TABLE #INDTAB;GOЗаявката в листинг 10 показва как можем да комбинираме низове с дати, изрично преобразувани в низове. Конкатенация на низове се използва за генериране на обща променлива за архивен път, която по-късно се използва във функцията SP_MSFOREACHDB.
--Списък 10 Генериране на общ път за архивиранеEXEC SP_MSFOREACHDB @COMMAND1='ДЕКЛАРИРАНЕ @BACKUP SYSNAMESET @BACKUP=N''G:\BACKUP\?''+CONVERT(NVARCHAR,GETDATE(),112)+N'' .BAK''USE [?]АКО ''?'' НЕ В ("MODEL","TEMPDB")ЗАПОЧВА БАЗА ДАННИ ЗА РЕЗЕРВНО КОПИРАНЕ ? ЗА ДИСК =@BACKUP С INIT , NOUNLOAD , КОМПРЕСИЯ, ИМЕ =N''?'', NOSKIP , NOFORMATEND'Заключение
В тази статия показахме няколко начина за използване на конкатенация в SQL Server. Дадохме примери за функцията CONCAT, функцията CONCAT_WS и използването на знака „+“. И трите метода могат да бъдат много полезни при генериране на изявления чрез комбиниране на стойности от различни колони или просто за показване на информация в желания удобен за хората формат. Документацията на Microsoft съдържа повече информация за синтаксиса и възможностите на тези функции.
Препратки
Преобразуване и конвертиране (Transact-SQL)
Concat Transact-SQL
Concat_ws Transact-SQL
Конкатенация на низове