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

文字列内のすべてのキーフィールドをT-SQLのテーブルの置換値に置き換えるにはどうすればよいですか?

    これを行うにはいくつかの方法があります。 2つの方法をリストします。それぞれに長所と短所があります。私は個人的に最初のもの(動的SQL)を使用します。

    1。動的SQL

    • 利点:高速で、再帰を必要としません
    • 短所:テーブル変数の更新には使用できません

    2。再帰CTE

    • 利点:テーブル変数の更新が可能です
    • 短所:再帰が必要であり、メモリを大量に消費します。再帰CTEは低速です

    1.A。動的SQL:通常のテーブルと一時テーブル。

    この例では、テキストソースとして一時テーブルを使用しています:

    CREATE TABLE #tt_text(templatebody VARCHAR(MAX));
    INSERT INTO #tt_text(templatebody)VALUES
        ('This is to inform #first_name# about the issues regarding #location#');
    
    CREATE TABLE #tt_repl(variable VARCHAR(256),template_value VARCHAR(8000));
    INSERT INTO #tt_repl(variable,template_value)VALUES
        ('#first_name#','Joseph William'),
        ('#location#','Alaska');
    
    DECLARE @rep_call NVARCHAR(MAX)='templatebody';
    SELECT
        @rep_call='REPLACE('[email protected]_call+','''+REPLACE(variable,'''','''''')+''','''+REPLACE(template_value,'''','''''')+''')'
    FROM
        #tt_repl;
    
    DECLARE @stmt NVARCHAR(MAX)='SELECT '[email protected]_call+' FROM #tt_text';
    EXEC sp_executesql @stmt;
    
    /* Use these statements if you want to UPDATE the source rather than SELECT from it
    DECLARE @stmt NVARCHAR(MAX)='UPDATE #tt_text SET templatebody='[email protected]_call;
    EXEC sp_executesql @stmt;
    SELECT * FROM #tt_text;*/
    
    DROP TABLE #tt_repl;
    DROP TABLE #tt_text;
    

    1.B。動的SQL:テーブル変数。

    テーブルを特定のテーブルタイプとして定義する必要があります。タイプ定義の例:

    CREATE TYPE dbo.TEXT_TABLE AS TABLE(
        id INT IDENTITY(1,1) PRIMARY KEY,
        templatebody VARCHAR(MAX)
    );
    GO
    

    このタイプのテーブル変数を定義し、次のように動的SQLステートメントで使用します。この方法でテーブル変数を更新することはできないことに注意してください。

    DECLARE @tt_text dbo.TEXT_TABLE;
    INSERT INTO @tt_text(templatebody)VALUES
        ('This is to inform #first_name# about the issues regarding #location#');
    
    DECLARE @tt_repl TABLE(id INT IDENTITY(1,1),variable VARCHAR(256),template_value VARCHAR(8000));
    INSERT INTO @tt_repl(variable,template_value)VALUES
        ('#first_name#','Joseph William'),
        ('#location#','Alaska');
    
    DECLARE @rep_call NVARCHAR(MAX)='templatebody';
    SELECT
        @rep_call='REPLACE('[email protected]_call+','''+REPLACE(variable,'''','''''')+''','''+REPLACE(template_value,'''','''''')+''')'
    FROM
        @tt_repl;
    
    DECLARE @stmt NVARCHAR(MAX)='SELECT '[email protected]_call+' FROM @tt_text';
    EXEC sp_executesql @stmt,N'@tt_text TEXT_TABLE READONLY',@tt_text;
    

    2。再帰CTE:

    再帰CTEを使用してこれを作成する唯一の理由は、テーブル変数を更新する予定であるか、何らかの方法で動的SQLを使用することが許可されていないことです(会社のポリシーなど)。

    デフォルトの最大再帰レベルは100であることに注意してください。100を超える置換変数がある場合は、OPTION(MAXRECURSION 32767)を追加してこのレベルを上げる必要があります。 クエリの最後(クエリのヒント を参照) -MAXRECURSION

    DECLARE @tt_text TABLE(id INT IDENTITY(1,1),templatebody VARCHAR(MAX));
    INSERT INTO @tt_text(templatebody)VALUES
        ('This is to inform #first_name# about the issues regarding #location#');
    
    DECLARE @tt_repl TABLE(id INT IDENTITY(1,1),variable VARCHAR(256),template_value VARCHAR(8000));
    INSERT INTO @tt_repl(variable,template_value)VALUES
        ('#first_name#','Joseph William'),
        ('#location#','Alaska');
    
    ;WITH cte AS (
        SELECT
            t.id,
            l=1,
            templatebody=REPLACE(t.templatebody,r.variable,r.template_value)
        FROM
            @tt_text AS t
            INNER JOIN @tt_repl AS r ON r.id=1
        UNION ALL
        SELECT
            t.id,
            l=l+1,
            templatebody=REPLACE(t.templatebody,r.variable,r.template_value)
        FROM
            cte AS t
            INNER JOIN @tt_repl AS r ON r.id=t.l+1
    )
    UPDATE
        @tt_text
    SET
        templatebody=cte.templatebody
    FROM
        @tt_text AS t
        INNER JOIN cte ON 
            cte.id=t.id
    WHERE
        cte.l=(SELECT MAX(id) FROM @tt_repl);
    
    /* -- if instead you wanted to select the replaced strings, comment out 
       -- the above UPDATE statement, and uncomment this SELECT statement:
    SELECT 
        templatebody 
    FROM 
        cte 
    WHERE 
        l=(SELECT MAX(id) FROM @tt_repl);*/
    
    SELECT*FROM @tt_text;
    


    1. 複数のnからnを持つmysqlselect

    2. データベースリンクを介してOracleでストアド関数(ユーザー定義型の配列を返す)を呼び出す

    3. mysqlを使用して1つのテーブルから別のテーブルに欠落しているレコードを挿入します

    4. MySQLの日時フィールドにNULL値を保存する方法は?