Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak zastąpić wszystkie pola kluczy w ciągu wartościami zastępczymi z tabeli w T-SQL?

Można to zrobić na kilka sposobów. Wymienię dwa sposoby. Każdy z nich ma zalety i wady. Osobiście użyłbym pierwszego (Dynamic SQL).

1. Dynamiczny SQL

  • Zalety:Szybki, nie wymaga rekurencji
  • Wady:nie można używać do aktualizacji zmiennych tabeli

2. Rekurencyjne CTE

  • Zalety:Umożliwia aktualizacje zmiennych tabeli
  • Wady:wymaga rekurencji i wymaga dużej ilości pamięci, rekurencyjne CTE są wolne

1.A. Dynamiczny SQL:tabele zwykłe i tabele tymczasowe.

W tym przykładzie jako źródło tekstu użyto tabeli tymczasowej:

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. Dynamiczny SQL:zmienne tabeli.

Wymaga zdefiniowania tabeli jako określonego typu tabeli. Przykładowa definicja typu:

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

Zdefiniuj zmienną tabeli tego typu i użyj jej w instrukcji dynamicznego SQL w następujący sposób. Pamiętaj, że aktualizacja zmiennej tabeli w ten sposób nie jest możliwa.

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

Jedynym powodem, dla którego napisałbyś to za pomocą rekurencyjnego CTE, jest to, że zamierzasz zaktualizować zmienną tabeli lub nie możesz w jakiś sposób używać Dynamic SQL (np. Polityka firmy?).

Zauważ, że domyślny maksymalny poziom rekurencji to 100. Jeśli masz więcej niż 100 zmiennych zastępczych, powinieneś zwiększyć ten poziom, dodając OPTION(MAXRECURSION 32767) na końcu zapytania (zobacz Wskazówki dotyczące zapytań - 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL:podobne a zawiera — różne wyniki

  2. Jak znaleźć wszystkie wystąpienia określonego tekstu we wszystkich procedurach składowanych w mojej bazie danych?

  3. Kopia zapasowa SQL Server 2017 -1

  4. Nulls i instrukcja MERGE:Muszę ustawić wartość na nieskończoność. Jak?

  5. SQL Async Wiele zapytań łączy wyniki — maksymalna liczba wyników (górne XYZ)