sql >> Database >  >> RDS >> Sqlserver

Hoe kan ik alle sleutelvelden in een string vervangen door vervangende waarden uit een tabel in T-SQL?

Er zijn verschillende manieren waarop dit kan worden gedaan. Ik noem twee manieren. Elk heeft voor- en nadelen. Ik zou persoonlijk de eerste gebruiken (Dynamic SQL).

1. Dynamische SQL

  • Voordelen:snel, vereist geen recursie
  • Nadelen:kan niet worden gebruikt om tabelvariabelen bij te werken

2. Recursieve CTE

  • Voordelen:staat updates van tabelvariabelen toe
  • Nadelen:vereist recursie en is geheugenintensief, recursieve CTE's zijn traag

1.A. Dynamische SQL:gewone tabellen en tijdelijke tabellen.

Dit voorbeeld gebruikt een tijdelijke tabel als tekstbron:

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. Dynamische SQL:tabelvariabelen.

Vereist dat de tabel is gedefinieerd als een specifiek tabeltype. Voorbeeld typedefinitie:

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

Definieer een tabelvariabele van dit type en gebruik deze als volgt in een Dynamic SQL-instructie. Merk op dat het op deze manier niet mogelijk is om een ​​tabelvariabele bij te werken.

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. Recursieve CTE:

De enige redenen waarom u dit zou schrijven met een recursieve CTE, is dat u van plan bent een tabelvariabele bij te werken, of dat u op de een of andere manier geen Dynamic SQL mag gebruiken (bijvoorbeeld bedrijfsbeleid?).

Merk op dat het standaard maximale recursieniveau 100 is. Als u meer dan 100 vervangingsvariabelen heeft, moet u dit niveau verhogen door OPTION(MAXRECURSION 32767) toe te voegen. aan het einde van de query (zie Query Hints - 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. Positioneringstabellen en grafieken in BIDS SSRS

  2. mysql_install_db, fout:35, op een Mac OS X 10.9.1

  3. LibreOffice:'com.mysql.jdbc.driver' kan niet worden geladen

  4. Krijg een vreemde fout, SQL Server-query met behulp van de `WITH`-clausule