sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo puedo reemplazar todos los campos clave en una cadena con valores de reemplazo de una tabla en T-SQL?

Hay varias formas de hacerlo. Voy a enumerar dos formas. Cada uno tiene ventajas y desventajas. Yo personalmente usaría el primero (SQL dinámico).

1. SQL dinámico

  • Ventajas:Rápido, no requiere recursividad
  • Desventajas:no se puede usar para actualizar las variables de la tabla

2. CTE recursivo

  • Ventajas:Permite actualizaciones de variables de tabla
  • Desventajas:requiere recursividad y requiere mucha memoria, los CTE recursivos son lentos

1.A. SQL dinámico:tablas regulares y tablas temporales.

Este ejemplo utiliza una tabla temporal como fuente de texto:

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 dinámico:variables de tabla.

Requiere tener la tabla definida como un tipo de tabla específico. Ejemplo de definición de tipo:

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

Defina una variable de tabla de este tipo y utilícela en una declaración de SQL dinámico de la siguiente manera. Tenga en cuenta que no es posible actualizar una variable de tabla de esta manera.

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

Las únicas razones por las que escribiría esto usando un CTE recursivo es que tiene la intención de actualizar una variable de tabla, o no tiene permitido usar Dynamic SQL de alguna manera (por ejemplo, ¿política de la empresa?).

Tenga en cuenta que el nivel de recurrencia máximo predeterminado es 100. Si tiene más de 100 variables de reemplazo, debe aumentar este nivel agregando OPTION(MAXRECURSION 32767) al final de la consulta (consulte Sugerencias de consulta - 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;