Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment puis-je remplacer tous les champs clés d'une chaîne par des valeurs de remplacement d'une table dans T-SQL ?

Cela peut être fait de plusieurs façons. Je vais énumérer deux façons. Chacun a des avantages et des inconvénients. Personnellement, j'utiliserais le premier (Dynamic SQL).

1. SQL dynamique

  • Avantages :Rapide, ne nécessite pas de récursivité
  • Inconvénients :ne peut pas être utilisé pour mettre à jour les variables de table

2. CTE récursif

  • Avantages :Permet les mises à jour des variables de table
  • Inconvénients :Nécessite une récursivité et consomme beaucoup de mémoire, les CTE récursifs sont lents

1.A. SQL dynamique :tables régulières et tables temporaires.

Cet exemple utilise une table temporaire comme source de texte :

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 dynamique :variables de table.

Nécessite que la table soit définie comme un type de table spécifique. Exemple de définition de type :

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

Définissez une variable de table de ce type et utilisez-la dans une instruction Dynamic SQL comme suit. Notez que la mise à jour d'une variable de table de cette manière n'est pas possible.

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 récursif :

Les seules raisons pour lesquelles vous écririez ceci en utilisant un CTE récursif sont que vous avez l'intention de mettre à jour une variable de table, ou que vous n'êtes pas autorisé à utiliser Dynamic SQL d'une manière ou d'une autre (par exemple, la politique de l'entreprise ?).

Notez que le niveau de récursivité maximum par défaut est de 100. Si vous avez plus de 100 variables de remplacement, vous devez augmenter ce niveau en ajoutant OPTION(MAXRECURSION 32767) à la fin de la requête (voir Indices de requête - 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;