【问题标题】:How to make a nested replace of values from another table?如何嵌套替换另一个表中的值?
【发布时间】:2018-01-29 17:11:22
【问题描述】:

我有两个具有以下(虚拟)结构的表:

Table 1
idText     sText(nvarchar(500))
1           Text with some keywords
2           Text2 with one keyword
3           Text3 with three keywords

Table 2 
idText    idKey    sKeyword  
1           1       some
1           2       keywords
2           3       one
3           4       with
3           2       keywords
3           5       three

有没有办法在Table2的所有相关关键字之间执行嵌套替换?

有一些解决方案,比如创建一个函数,但我认为这不是一个好的解决方案,因为它不会在其他任何地方重用。我也尝试过递归 CTE,但没有成功。

结果一定是这样的:

Table 1
idText     sText(nvarchar(500))
1           Text with Replaced_some Replaced_keywords
2           Text2 with Replaced_one keyword
3           Text3 Replaced_with Replaced_three Replaced_keywords

PS。

  • Replaced 字符串已修复。所以你可以使用你喜欢的字符串。替换语句是这样的:replace(sText, sKeyword, 'Replaced_' + sKeyowrd)
  • IdKey 在这种情况下是无用的,但它是我们真实数据库结构的一部分

这是我使用递归 CTE 失败的尝试:

DECLARE @Table1 TABLE(  ID int,   sText nvarchar(200))
DECLARE @Table2 TABLE(  ID int,   sKeyword nvarchar(10))

INSERT INTO @Table1 VALUES(1, 'Text with some keywords')
INSERT INTO @Table1 VALUES(2, 'Text2 with one keyword')
INSERT INTO @Table1 VALUES(3, 'Text3 with three keywords')

INSERT INTO @Table2 VALUES(1, 'some')
INSERT INTO @Table2 VALUES(1, 'keywords')
INSERT INTO @Table2 VALUES(2, 'one')
INSERT INTO @Table2 VALUES(3, 'with')
INSERT INTO @Table2 VALUES(3, 'keywords')
INSERT INTO @Table2 VALUES(3, 'three')

;WITH CTE AS(

SELECT ID, sText FROM @Table1 
UNION ALL
SELECT c.ID, CAST(REPLACE(sText, sKeyword, 'New_' + sKeyword) AS nvarchar(200))  FROM CTE c 
INNER JOIN @Table2 t2 ON t2.ID = c.ID
) 
SELECT * FROM CTE 

结果是一个无限循环,它不会停止。

任何帮助将不胜感激

【问题讨论】:

  • “Replaced_some”从何而来?它是在表格中,还是只是在每个关键字之前添加“Replaced_”?请发布您使用递归 CTE 的尝试,以便我们对其进行调试。
  • 我想我可以看到您将替换的内容,但看不到您将替换它的内容 with,这似乎是解决方案所必需的。
  • idKey 是干什么用的?
  • 我编辑问题以使其更清晰。谢谢@KtX2SkD
  • 请同时发布您解决此问题的尝试以及为什么它不起作用。

标签: sql sql-server sql-server-2008


【解决方案1】:

免责声明:按承诺精简功能,将适时更新答案描述。

根据我目前对您的问题的理解,我想我可以应用我设计的一个函数来解决我最近遇到的一个更复杂的问题。可能还有其他解决方案,但大多数肯定其他人可以并且会提出它们,所以我为什么不为您提供一些可以提供的东西。

请注意,它的目的是解决比您的更复杂的问题稍后解释),现在我很遗憾没有'没时间把它瘦下来,但我可能明天会去。我希望cmets有所帮助。无论如何,我将为您总结一下我的职能目标:

有一个表格,其中包含要查找的消息以及替换它们的内容。该函数将接收一个文本值作为输入,将使用游标循环所述表,并且对于所述表中的每条记录,它将检查输入文本是否包含要替换的内容,如果适用则替换。

关于最初的目标有两点需要注意。 首先,有一个嵌套循环来解决某个关键字多次存在的情况,因此需要多次替换。 其次,我还必须处理通配符、可变长度以及是否在讨论的表格中设置了替换标志。这两件事加上其他可能是你会发现很多奇怪的材料飞来飞去的原因。

CREATE FUNCTION [JACKINABOX](@TextToUpdate varchar(30), @FilterId int)
RETURNS varchar(30) AS
BEGIN

    DECLARE @Keyword varchar(30)

    DECLARE LonelyCursor CURSOR FOR
        SELECT Keyword FROM ReplacementInformation WHERE Id = @FilterId

    OPEN LonelyCursor ; FETCH NEXT FROM LonelyCursor INTO @Keyword

    WHILE @@FETCH_STATUS = 0 -- While there still remains keywords to process.
    BEGIN
        WHILE 1 = 1 -- Not sure, but I think this nested loop can be unlooped if [FETCH NEXT] was cut & pasted to replace [BREAK].
        BEGIN
            IF(CHARINDEX(@Keyword, @TextToUpdate) = 0)
                BREAK -- If cannot find current keyword anymore, move on to next keyword.
            ELSE -- Otherwise, update text then check again for same keyword.
                SET @TextToUpdate = REPLACE(@TextToUpdate, @Keyword, CONCAT('Replaced_', @Keyword))
        END
        FETCH NEXT FROM LonelyCursor INTO @Keyword
    END

    CLOSE LonelyCursor ; DEALLOCATE LonelyCursor

    RETURN @TextToUpdate

END

【讨论】:

  • 感谢您的尝试,但光标在大多数情况下是一个糟糕的选择。此外,我在问题中表示我正在寻找不使用函数的解决方案。
  • @Ayorus,按照约定清理代码。与大多数其他东西相比,游标确实效率低下,但它们确实很出色,在某些情况下甚至是必需的。这种情况是否如此,我不能肯定地说,但一个缓慢的解决方案总比没有好,而且在我的问题中,它几乎是即时的。我建议您试用并评估,尤其是我猜它几乎可以申请了。
  • 另外,@Ayorus,我认为 "no function" 问题是针对开发开销,而不是权限限制,这就是我提出的原因我的功能。尽管如此,我几乎可以肯定 它可以重写 以在函数范围之外使用,即使使用循环而不是游标也是如此。希望我可以为您审查您的 CTE,但我对 CTE 从来都不擅长。
  • 感谢您的 cmets 和帮助。谢谢@KtX2SkD
猜你喜欢
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
相关资源
最近更新 更多