首页 > 解决方案 > '合并字段' - 类似于 SQL Server 功能

问题描述

我试图找到一种方法让 SGBD 在长文本中执行大量合并字段。

创建结构:

CREATE TABLE [dbo].[store]
(
    [id] [int] NOT NULL,
    [text] [nvarchar](MAX) NOT NULL
)

CREATE TABLE [dbo].[statement]
(
    [id] [int] NOT NULL,
    [store_id] [int] NOT NULL
)

CREATE TABLE [dbo].[statement_merges]
(
    [statement_id] [int] NOT NULL,
    [merge_field] [nvarchar](30) NOT NULL,
    [user_data] [nvarchar](MAX) NOT NULL
)

现在,创建测试值

INSERT INTO [store] (id, text) 
VALUES (1, 'Waw, stackoverflow is an amazing library of lost people in the IT hell, and i have the feeling that $$PERC_SAT$$ of the users found a solution, personally I asked $$ASKED$$ questions.')

INSERT INTO [statement] (id, store_id) 
VALUES (1, 1)

INSERT INTO [statement_merges] (statement_id, merge_field, user_data) 
VALUES (1, '$$PERC_SAT$$', '85%')

INSERT INTO [statement_merges] (statement_id, merge_field, user_data) 
VALUES (1, '$$ASKED$$', '12')

目前我的应用程序正在交付最终语句,循环合并,替换存储的文本和输出

哇,stackoverflow 是一个令人惊叹的 IT 地狱迷路者库,我感觉 85% 的用户找到了解决方案,我个人问了 12 个问题。

我试图找到一种独立于代码的方法,并在单个查询中提供输出,正如您所理解的,选择一个语句,其中存储的文本已经填充了用户数据。我希望我很清楚。

我查看了 TRANSLATE 函数,但它看起来像一个字符替换,所以我有两个选择:

考虑到我想要这个,因为真实的文本很长,我不想在我的数据库中多次存储它。您可以想象一份只有 12 个参数的 3 页合同,例如开始日期、发票金额等……其他所有内容都无法更改以确保合规性。

感谢您的时间!

编辑 :

感谢 Randy 的帮助,这看起来可以解决问题:

WITH cte_replace_tokens AS (

    SELECT replace(r.text, m.merge_field, m.user_data) as [final], m.merge_field, s.id, 1 AS i
    FROM store r
    INNER JOIN statement s ON s.store_id = r.id
    INNER JOIN statement_merges m ON m.statement_id = s.id
    WHERE m.statement_id = 1

    UNION ALL

    SELECT replace(r.final, m.merge_field, m.user_data) as [final], m.merge_field, r.id, r.i + 1 AS i
    FROM cte_replace_tokens r
    INNER JOIN statement_merges m ON m.statement_id = r.id
    WHERE m.merge_field > r.merge_field

) 

select TOP 1 final from cte_replace_tokens ORDER BY i DESC

如果性能好,我将检查更大的数据库......

至少,我可以“填充”一个语句,我需要弄清楚也能够提取一个列表。

再次感谢 !

标签: sqlsql-serverreplacerecursive-query

解决方案


如果同一更新多次更新记录,则最后一次获胜。没有任何更新受到其他更新的影响 - 没有累积效应。在某些情况下,可以使用局部变量来欺骗 SQL 以获得累积效应,但这很棘手,不推荐使用。(顺序变得很重要,并且在更新中不可靠。)

一种替代方法是 CTE 中的递归。在替换每个标记时,从先前的记录中生成一条新记录,直到没有标记为止。这是一个工作示例,将 1 替换为 A,将 2 替换为 B,等等。(我想知道是否有一些棘手的 xml 也可以做到这一点。)

if not object_id('tempdb..#Raw') is null drop table #Raw
CREATE TABLE #Raw(
    [test] [varchar](100) NOT NULL PRIMARY KEY CLUSTERED,
)

if not object_id('tempdb..#Token') is null drop table #Token
CREATE TABLE #Token(
    [id] [int] NOT NULL PRIMARY KEY CLUSTERED,
    [token] [char](1) NOT NULL,
    [value] [char](1) NOT NULL,
)

insert into #Raw values('123456'), ('1122334456')
insert into #Token values(1, '1', 'A'), (2, '2', 'B'), (3, '3', 'C'), (4, '4', 'D'), (5, '5', 'E'), (6, '6', 'F');

WITH cte_replace_tokens AS (

    SELECT r.test, replace(r.test, l.token, l.value) as [final], l.id
    FROM [Raw] r
    CROSS JOIN #Token l
    WHERE l.id = 1

    UNION ALL

    SELECT r.test, replace(r.final, l.token, l.value) as [final], l.id
    FROM cte_replace_tokens r
    CROSS JOIN #Token l
    WHERE l.id = r.id + 1

) 
select * from cte_replace_tokens where id = 6

推荐阅读