sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan kan jeg erstatte alle nøglefelter i en streng med erstatningsværdier fra en tabel i T-SQL?

Der er flere måder dette kan gøres på. Jeg vil nævne to måder. Hver enkelt har fordele og ulemper. Jeg ville personligt bruge den første (Dynamisk SQL).

1. Dynamisk SQL

  • Fordele:Hurtigt, kræver ikke rekursion
  • Ulempe:Kan ikke bruges til at opdatere tabelvariabler

2. Rekursiv CTE

  • Fordele:Tillader opdateringer af tabelvariabler
  • Ulempe:Kræver rekursion og er hukommelsesintensiv, rekursive CTE'er er langsomme

1.A. Dynamisk SQL:Almindelige tabeller og Midlertidige tabeller.

Dette eksempel bruger en midlertidig tabel som tekstkilde:

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. Dynamisk SQL:Tabelvariabler.

Kræver at have tabellen defineret som en specifik tabeltype. Eksempel på typedefinition:

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

Definer en tabelvariabel af denne type, og brug den i en dynamisk SQL-sætning som følger. Bemærk, at det ikke er muligt at opdatere en tabelvariabel på denne måde.

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

De eneste grunde til, at du ville skrive dette ved hjælp af en rekursiv CTE, er, at du har til hensigt at opdatere en tabelvariabel, eller at du på en eller anden måde ikke må bruge Dynamic SQL (f.eks. virksomhedspolitik?).

Bemærk, at standard maksimum rekursionsniveau er 100. Hvis du har mere end 100 erstatningsvariabler, bør du øge dette niveau ved at tilføje OPTION(MAXRECURSION 32767) i slutningen af ​​forespørgslen (se Forespørgselstip - 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. Division ( / ) giver ikke mit svar i postgresql

  2. Søg i en streng efter et regulært udtryksmønster og erstat hver forekomst som en afledning af sig selv i oracle SQL

  3. Oracle SQLPlus indstilling af miljøvariabel baseret på variabel

  4. beregne pris mellem givne datoer