sql - '合并字段' - 类似于 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 函数,但它看起来像一个字符替换,所以我有两个选择:
- 我尝试了一个递归函数,一个一个地替换,直到
merge_fields
在计算的文本中没有找到;但我对这种方法的性能表示怀疑; - 有一种魔法可以做到这一点,但我需要你的知识......
考虑到我想要这个,因为真实的文本很长,我不想在我的数据库中多次存储它。您可以想象一份只有 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
如果性能好,我将检查更大的数据库......
至少,我可以“填充”一个语句,我需要弄清楚也能够提取一个列表。
再次感谢 !
解决方案
如果同一更新多次更新记录,则最后一次获胜。没有任何更新受到其他更新的影响 - 没有累积效应。在某些情况下,可以使用局部变量来欺骗 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
推荐阅读
- discord.js - 当所有者不可见时无法读取未定义的属性“用户”,导致 BOT 崩溃
- sql - 在 laravel 7 中将 DB:select() 转换为查询构建器
- javascript - 在 JavaScript 中对 body 或其他 HTML 元素的任何更新设置回调
- mongodb - 如何为远程连接启用密码身份验证并为 MongoDB 本地禁用它?
- assembly - 填充动态分配的内存会冻结程序执行
- javascript - 如何多次运行 Bootstrap Alert?
- javascript - 未捕获的语法错误:JSON.parse 中位置 1 的 JSON 中的意外标记和 (
) - php - 为什么我不能在 php 中做评论( /* 像这个 */ )?
- node.js - 将快递端代码重构为更易使用的格式
- c# - DB First Entity Framework Core 中的 Oracle 将 NUMBER(3) 映射到字节导致运行时异常