Ian*_*oyd 1 t-sql sql-server recursive-query
我发现了一些 T-SQL 代码,我试图弄清楚它是否是:
\n我们有一个要求尝试清理名称:
\nBob\xe2\x86\x92RobertBill\xe2\x86\x92WilliamDick\xe2\x86\x92Richard因此创建了一个表来保存该值以及将其替换为的值。它包含上述单词(以及更深奥的、特定领域的、特定行业的映射):
\n填充词:
\n| 价值 | 用。。。来代替 |
|---|---|
| 迪克 | 理查德 |
| 账单 | 威廉 |
| 鲍勃 | 罗伯特 |
| 特德 | 威廉 |
我看到的用于执行替换的代码要么是天才,要么是疯狂:
\nDECLARE @firstName varchar(200) = \'bill\';\nSELECT @firstName = REPLACE(@firstName, FillerWords.Value, FillerWords.ReplaceWith) FROM FillerWords;\nSELECT @firstName;\nRun Code Online (Sandbox Code Playgroud)\n这使:
\n(no column name)\n----------------\nWilliam\n\n1 row(s) affected\nRun Code Online (Sandbox Code Playgroud)\n更令人印象深刻的是它可以一次进行多个替换:
\nDECLARE @firstName varchar(200) = \'teddickbobbill\';\nSELECT @firstName = REPLACE(@firstName, FillerWords.Value, FillerWords.ReplaceWith) FROM FillerWords;\nSELECT @firstName;\nRun Code Online (Sandbox Code Playgroud)\n这使:
\n(no column name)\n----------------\nWilliamRichardRobertWilliam\n\n1 row(s) affected\nRun Code Online (Sandbox Code Playgroud)\n它有效,但有效吗?
\n如果在选择过程中消除变量赋值:
\nSELECT REPLACE(@firstName, fw.Value, fw.ReplaceWith) FROM #FillerWords fw\nRun Code Online (Sandbox Code Playgroud)\n您会看到它正在对REPLACE表中的每一行执行:
(No column name)\nteddickRobertbill\ntedRichardbobbill\nWilliamdickbobbill\nteddickbobWilliam\nRun Code Online (Sandbox Code Playgroud)\n因此,每次计算一行时,@firstName都会更新变量:
| @名 | 价值 | 用。。。来代替 | @firstName 的新值 |
|---|---|---|---|
| 泰迪克鲍比尔 | 迪克 | 理查德 | 特德Richard·鲍比尔 |
| 特德·理查德·博比尔 | 账单 | 威廉 | 特德·理查德·鲍勃William |
| 泰德·理查德·鲍勃·威廉 | 鲍勃 | 罗伯特 | 特德·理查德Robert·威廉 |
| 特德·理查德·罗伯特·威廉 | 特德 | 威廉 | William理查德·罗伯特·威廉 |
因此,它似乎依赖于变量赋值的一个怪癖,即您可以不断地逐行修改相同的变量;这几乎就像一个光标操作。
\n是否支持这种 T-SQL 编程风格?我知道递归公用表表达式(CTE)一直在这样做;但这里允许吗?
\n我知道代码的成功取决于处理行的顺序,这在 SQL 中通常无法保证。这可能会导致结果不一致,尤其是当基础数据或 SQL Server 的查询执行计划发生更改时。在这个问题中,我不关心这个。
\n我问了一位分析基数的神谕机制,它说:
\n\n\n该代码利用了 T-SQL 的特定行为,其中可以在 SELECT 语句中更新变量。然而,这不是标准的 SQL 行为,并且可能不直观或不可维护。虽然这在当前版本的 SQL Server 中有效,但不能保证此类行为在未来版本中保持一致或受支持,因为它不是用于此类目的的记录功能。
\n
递归设置变量不是可接受的模式吗?
\n这与旧的字符串聚合技术属于同一类,旧的字符串聚合技术有时有效,有时无效(取决于执行计划),并且从未成为受支持的技术。
该文档明确警告“反模式使用递归变量赋值”存档
你的代码:
SELECT @firstName = REPLACE(@firstName, ...)
FROM
Run Code Online (Sandbox Code Playgroud)
当然是对结构的警告:
SELECT @Var = <expression containing @Var>
FROM
Run Code Online (Sandbox Code Playgroud)
绝对不应该出现在您关心的生产代码中,因为它不能保证工作。
在字符串连接方法“失败”的情况下,变量的结果值仅包含单个赋值的结果,因此我预计有可能获得一个仅有效执行单个赋值的计划REPLACE。