Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как мога да заменя всички ключови полета в низ със заместващи стойности от таблица в T-SQL?

Има няколко начина, по които това може да стане. Ще изброя два начина. Всеки от тях има предимства и недостатъци. Аз лично бих използвал първия (Dynamic SQL).

1. Динамичен SQL

  • Предимства:Бързо, не изисква рекурсия
  • Недостатъци:Не може да се използва за актуализиране на променливи на таблица

2. Рекурсивен CTE

  • Предимства:Позволява актуализиране на променливите на таблицата
  • Недостатъци:Изисква рекурсия и изисква интензивна памет, рекурсивните CTE са бавни

1.A. Динамичен SQL:Редовни таблици и Временни таблици.

Този пример използва временна таблица като източник на текст:

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.Б. Динамичен SQL:Таблични променливи.

Изисква таблицата да бъде дефинирана като конкретен тип таблица. Примерна дефиниция на тип:

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

Дефинирайте таблична променлива от този тип и я използвайте в израз на динамичен SQL, както следва. Имайте предвид, че актуализирането на променлива на таблица по този начин не е възможно.

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:

Единствените причини, поради които бихте написали това, като използвате рекурсивен CTE, са, че възнамерявате да актуализирате променлива на таблица или не ви е разрешено да използвате Dynamic SQL по някакъв начин (напр. фирмена политика?).

Имайте предвид, че максималното ниво на рекурсия по подразбиране е 100. Ако имате повече от 100 заместващи променливи, трябва да увеличите това ниво, като добавите OPTION(MAXRECURSION 32767) в края на заявката (вижте Съвети за заявка - 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 сървър

  2. Няма избран резервен набор за възстановяване SQL Server 2012

  3. Забравена парола за SQL Server

  4. Изграждане на динамична клауза WHERE в съхранена процедура

  5. Промяна на sql-сървър DB от табличен към многоизмерен