sql >> データベース >  >> RDS >> Database

Transact-SQLでの連結

    はじめに

    顧客データを含むテーブルを管理していて、上司から顧客の現在のリストとその電話番号を送信するように求められたとします。通常、データを抽出して、行と列を含むスプレッドシートを送信します。また、少しスタイリッシュにして、必要な情報をより人に優しい形式で送信することもできます。 SQL Serverは、英語の式とテーブル内のデータを組み合わせて、技術者以外の人が読みやすい出力を表示することで、これを実現できる関数を提供します。これらの機能は、より微妙な用途にも使用できます。

    CONCAT関数

    CONCAT関数は、2つ以上の文字列引数を受け入れ、そのような文字列の組み合わせを1つの式として返します。これは、さまざまな列の内容を単一の式として表示する場合に役立ちます。この関数の簡単な使用例をリスト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
    

    図1のスペースと結果を使用したこのステートメントのバリエーションに注意してください。

    図。 1.単純なCONCATステートメント

    INTデータ型の入力値でCONCATステートメントを使用しようとすると、SQL Serverは暗黙の変換を実行し、図2に示すように文字列出力を返します。これは、リスト2のステートメントの詳細。まず、関心のあるテーブルの構造を見てください。図2は、 PhoneNumber#を示しています。 およびFirstTranDate 列はそれぞれBIGINT列とDATETIME列です。

    図。 2.顧客テーブルの構造

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

    実行プランをざっと見てみると、SQLServerが暗黙の変換を実行していることがわかります。 PhoneNumber1列。これは、列がリスト4と図4に示す日付データ型の場合も同じです。CONCAT関数は、図6に示すグラフに概説されているルールに基づいて暗黙的な変換を実行します。

    図。 3.BIGINTデータ型の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;
    

    図。 4.の暗黙的な変換 DATETIMEデータ型からVARCHAR

    図。 5.BIGINTデータ型のVARCHARへの暗黙的な変換

    図。 6.SQLServerでのデータ型変換

    この関数の主な使用例は、上記のデモンストレーションから推測できます。例としては、ダッシュボードやWebページに、複数の列や個別のテーブルのデータを使用して、よりわかりやすい言語で情報を表示する必要がある場合があります。

    CONCAT_WS関数

    CONCAT_WS関数は、CONCAT関数の拡張です。これにより、最初のパラメーターとして目的のセパレーターを指定できます。リスト4は、リスト1で以前に使用したステートメントの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;
    

    CONCAT_WSを使用すると、各引数の後に引数としてスペースを導入する場合に比べて、区切り文字としてスペースを使用してステートメントを簡単に作成できることに注意してください。

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

    「+」記号との連結

    SQL Serverは、「+」記号の使用をサポートして、CONCAT関数がはるかに簡単な方法で実行することを実現します。このアプローチは通常、多数のオブジェクトに対して操作を実行する必要がある場合にT-SQLステートメントを生成するために使用されます。リスト7は、Examデータベース内のすべてのテーブルの統計更新バッチを生成する方法を示しています。

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

    2番目のステートメントの角括弧に注意してください。スペースや特殊文字を含むシステムオブジェクトを処理する場合に便利です。

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

    出力が生成されると、リスト7に示すように、任意のデータベースにユーザーを作成するために使用できます。関心のあるログイン名のフィルターを追加したことに注意してください。このアプローチは、あらゆる種類のステートメントを生成するために使用できます。同じセッション内でそのようなステートメントを呼び出します。より複雑な例は、データベース内のすべてのインデックスを創造的に再構築する次のステートメントです。 (リスト8および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
    

    リスト10のクエリは、文字列を明示的に文字列に変換された日付と組み合わせる方法を示しています。 文字列の連結 後で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'
    
    

    結論

    この記事では、SQLServerで連結を使用するいくつかの方法を示しました。 CONCAT関数、CONCAT_WS関数、および「+」記号の使用例を示しました。 3つの方法はすべて、異なる列の値を組み合わせてステートメントを生成したり、単に情報を必要な人にわかりやすい形式で表示したりするのに非常に役立ちます。 Microsoftのドキュメントには、これらの関数の構文と機能に関する詳細情報があります。

    参照

    キャストと変換(Transact-SQL)

    Concat Transact-SQL

    Concat_ws Transact-SQL

    文字列の連結


    1. Oracleの空の文字列

    2. MySQLでCASEステートメントを使用する方法

    3. MariaDBでのDAYOFMONTH()のしくみ

    4. テーブル式の基礎、パート13 –インラインテーブル値関数、続き