使用来自其他列的值查找和替换花括号中的值

Find and Replace values in curly braces with values coming from other column

我在编写 SQL 查询时遇到问题。

我有一个数据 table 包含以下几列。

数据表 1

              id     notes
           ----------------------------------------------------------------
             1      The Organization
             1      develop document disseminate to {{param = "ac-1_prm_1"}}
             2      develop document  to {{param = "ac-1_prm_2"}}
             2       Test

数据table参数

 parameterid     value.                 Id
 -------------------------------—————----------------
 ac-1_prm_1      apple doc.              1
 ac-1_prm_2      google doc.             1
 ac-1_prm_3      facebook doc.           2

我需要创建一个 final_notes 列:

 id  notes                                                       final_notes 
 ---------------------------------------------------------------------------------------------     
  1   The Organization                                  The Organization
  1   develop document disseminate                      develop document disseminate to apple 
     to{<!-- -->{param = "ac-1_prm_1"}}                 doc and google doc
     and {<!-- -->{param = "ac-1_prm_2"}}        
      
 
  2   develop document                                  develop document facebook doc 
      to {<!-- -->{param = "ac-1_prm_3"}}
  2   Test                                              Test

Sql 代码无效。

在我的代码中,我必须硬编码我不想要的值。

     DECLARE @DataTable TABLE (
      id int,
       notes varchar(1000)
       );
     INSERT INTO @DataTable VALUES 
    (1, 'Organization'),
    (1, 'develop document disseminate to {{param = "ac-1_prm_1"}} and 
    {{param = "ac-1_prm_2"}} '),
    (2, 'develop document  to {{param = "ac-1_prm_3"}}'),
    (2, 'test');

   DECLARE @DataTableParameter TABLE (
    parameterid varchar(100),
    [value] varchar(100),
    id int
   );
   INSERT INTO @DataTableParameter VALUES
   ('ac-1_prm_1', 'apple doc.', 1),
   ('ac-1_prm_2', 'google doc.', 1),
   ('ac-1_prm_3', 'facebook doc.', 2)

 ;WITH CTE AS (
 SELECT t1.id, t1.notes, t2.parameterid, t2.value 
 FROM @DataTable AS t1
 INNER  JOIN  @DataTableParameter AS t2 ON t1.id = t2.id
)
  SELECT 
 t.id, 
 REPLACE('develop document disseminate to {' + STUFF(
     (
         SELECT ', {' + parameterid + '}'
         FROM CTE 
         WHERE id = t.id 
         ORDER BY parameterid
         FOR XML PATH(''), TYPE
     ).value('.', 'NVARCHAR(MAX)'),
     1,
     1,
     ''
    ) + '}', ',', ' and ') AS notes,
   REPLACE(REPLACE('develop document disseminate to ' + STUFF(
     (
         SELECT ', ' + value
         FROM CTE 
         WHERE id = t.id 
         ORDER BY value
         FOR XML PATH(''), TYPE
     ).value('.', 'NVARCHAR(MAX)'),
     1,
     1,
     ''
 ), '.', ''), ',', ' and ') AS final_notes
   FROM CTE AS t
  GROUP BY t.id;

请尝试以下解决方案。

SQL

-- DDL and sample data population, start
DECLARE @DataTable TABLE (id int, notes varchar(1000));
INSERT INTO @DataTable VALUES 
(1, 'Organization'),
(1, 'develop document disseminate to {{param = "ac-1_prm_1"}} and 
{{param = "ac-1_prm_2"}} '),
(2, 'develop document  to {{param = "ac-1_prm_3"}}'),
(2, 'test');

DECLARE @DataTableParameter TABLE (parameterid varchar(100), [value] varchar(100), id int);
INSERT INTO @DataTableParameter VALUES
('ac-1_prm_1', 'apple doc.', 1),
('ac-1_prm_2', 'google doc.', 1),
('ac-1_prm_3', 'facebook doc.', 2);
-- DDL and sample data population, end

DECLARE @parameterid varchar(100), @value VARCHAR(100);
DECLARE @RowCount INT = (SELECT COUNT(*) FROM @DataTableParameter);

WHILE @RowCount > 0 BEGIN
   SELECT @parameterid = parameterid, @value = value
   FROM @DataTableParameter 
   ORDER BY ID DESC OFFSET @RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
   
   -- do whatever needed, apply any logic, call stored procedures, etc.
   UPDATE @DataTable
   SET notes = REPLACE(notes, CONCAT('{{param = "', @parameterid, '"}}'), @value);

   SET @RowCount -= 1;
END;

-- test
SELECT * FROM @DataTable;

输出

+----+--------------------------------------------------------------+
| id |                            notes                             |
+----+--------------------------------------------------------------+
|  1 | Organization                                                 |
|  1 | develop document disseminate to apple doc. and   google doc. |
|  2 | develop document  to facebook doc.                           |
|  2 | test                                                         |
+----+--------------------------------------------------------------+

递归 CTE 在这里可能会相当笨拙,因为您不能使用 TOP 并且您还必须仅过滤最终结果。

而是使用 table 变量或临时变量 table,并循环更新它。

DECLARE @results TABLE (id int, notes varchar(1000));

INSERT @results (id, notes)
SELECT id, notes
FROM @DataTable dt;

DECLARE @dtp varchar(100), @dtv varchar(100);

WHILE 1=1
BEGIN
    SELECT TOP (1)
        @dtp = dtp.parameterid,
        @dtv = dtp.value
    FROM @DataTableParameter dtp
    WHERE parameterid > @dtp OR @dtp IS NULL
    ORDER BY parameterid;

    IF @@ROWCOUNT = 0
        BREAK;
    
    UPDATE @results
    SET
        notes = REPLACE(notes, '{{param = "' + @dtp + '"}}', @dtv)
    FROM @results r
    WHERE notes LIKE '%' + @dtp + '%';
END;

SELECT *
FROM @results;

db<>fiddle

这可能是 古怪更新的情况:

CREATE DATABASE testDb_Shnugo;
GO
USE testDb_Shnugo;
GO

--用你的测试数据创建tables

CREATE TABLE dbo.DataTable (id INT, notes VARCHAR(1000));
INSERT INTO dbo.DataTable VALUES 
(1, 'The Organization'),
(1, 'develop document disseminate to {{param = "ac-1_prm_1"}} and {{param = "ac-1_prm_2"}} '),
(2, 'develop document  to {{param = "ac-1_prm_3"}}'),
(2, 'test');
GO

CREATE TABLE DataTableParameter (parameterid VARCHAR(100), [value] VARCHAR(100), id INT);
INSERT INTO DataTableParameter VALUES
('ac-1_prm_1', 'apple doc.', 1),
('ac-1_prm_2', 'google doc.', 1),
('ac-1_prm_3', 'facebook doc.', 2);
GO

--魔法来了:古怪的更新

CREATE FUNCTION dbo.MultiReplaceDataTableParameters(@inp VARCHAR(1000), @id INT)
RETURNS VARCHAR(1000)
AS
BEGIN
    DECLARE @result VARCHAR(1000)=@inp;
    SELECT @result = REPLACE(@result,CONCAT('{{param = "',dtp.parameterid,'"}}'),dtp.[value])
    FROM dbo.DataTableParameter dtp
    WHERE dtp.id=@id;

    RETURN @result;
END
GO

--试试看

SELECT *
     ,dbo.MultiReplaceDataTableParameters(dt.notes,dt.id) AS ReplacedText
FROM dbo.DataTable dt
ORDER BY dt.id;
GO

--清理(注意真实数据!

USE master;
GO

DROP DATABASE testDb_Shnugo;

简而言之:

古怪更新 遍历 table 的结果并使用声明的参数作为输入 分配。因此,该值将随着访问的任何行而变化。

这允许一次执行多项操作。

有充分的理由避免这种技术,但在这种情况下它可能会有所帮助。

1   The Organization
1   develop document disseminate to apple doc. and google doc. 
2   develop document  to facebook doc.
2   test