Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Làm cách nào để thay thế tất cả các trường khóa trong một chuỗi bằng các giá trị thay thế từ một bảng trong T-SQL?

Có một số cách có thể được thực hiện. Tôi sẽ liệt kê hai cách. Mỗi cái đều có ưu điểm và nhược điểm. Cá nhân tôi sẽ sử dụng cái đầu tiên (SQL động).

1. SQL động

  • Ưu điểm:Nhanh chóng, không yêu cầu đệ quy
  • Nhược điểm:Không thể được sử dụng để cập nhật các biến bảng

2. CTE đệ quy

  • Ưu điểm:Cho phép cập nhật các biến bảng
  • Nhược điểm:Yêu cầu đệ quy và tốn nhiều bộ nhớ, CTE đệ quy chậm

1.A. SQL động:Bảng thông thường và bảng tạm thời.

Ví dụ này sử dụng một bảng tạm thời làm nguồn văn bản:

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 động:Biến bảng.

Yêu cầu phải xác định bảng là một loại bảng cụ thể. Định nghĩa kiểu mẫu:

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

Xác định một biến bảng thuộc loại này và sử dụng nó trong một câu lệnh SQL động như sau. Lưu ý rằng không thể cập nhật biến bảng theo cách này.

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 đệ quy:

Lý do duy nhất tại sao bạn viết điều này bằng cách sử dụng CTE đệ quy là bạn có ý định cập nhật một biến bảng hoặc bạn không được phép sử dụng Dynamic SQL bằng cách nào đó (ví dụ:chính sách của công ty?).

Lưu ý rằng mức đệ quy tối đa mặc định là 100. Nếu bạn có hơn 100 biến thay thế, bạn nên tăng mức này bằng cách thêm OPTION(MAXRECURSION 32767) ở cuối truy vấn (xem Gợi ý Truy vấn - 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. Làm thế nào để xác định số ngày trong một tháng trong SQL Server?

  2. Có thể thêm ngôn ngữ vào sys.syslanguages ​​trong SQL Server 2008 không?

  3. NCHAR (1) so với BIT

  4. Duy trì mối quan hệ cha-con khi sao chép dữ liệu phân cấp

  5. 3 cách lấy danh sách cơ sở dữ liệu trong SQL Server (T-SQL)