Sql 在这种情况下,是否可以使用基于集合的循环来代替游标循环?
当前代码:Sql 在这种情况下,是否可以使用基于集合的循环来代替游标循环?,sql,sql-server,Sql,Sql Server,当前代码: DECLARE thisLoop CURSOR FOR SELECT IdOld, IdNew FROM @fieldNewOld; OPEN thisLoop; FETCH NEXT FROM thisLoop INTO @fIdOld, @fIdNew; WHILE @@FETCH_STATUS = 0 BEGIN UPDATE dbo.mel SET melCode = REPLACE(melCode, '_' + CONVERT(va
DECLARE thisLoop CURSOR FOR
SELECT IdOld, IdNew
FROM @fieldNewOld;
OPEN thisLoop;
FETCH NEXT FROM thisLoop INTO @fIdOld, @fIdNew;
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE dbo.mel
SET melCode = REPLACE(melCode, '_' + CONVERT(varchar(50),@fIdOld), '_' + CONVERT(varchar(50),@fIdNew))
where fID = (select IdNew from @newForm) and melCode LIKE ('%_' + CONVERT(varchar(50), @fIdOld) + '%')
FETCH NEXT FROM thisLoop INTO @fIdOld, @fIdNew
END;
CLOSE thisLoop;
DEALLOCATE thisLoop;
这方面的工作还有很多,但基本上我是在复制一个数据集@fieldNewOld包含旧id和新id。dbo.mel中的melCode包含用专有语言编写的代码,可以引用所有旧id。它将被引用为类似“myVar_1234”的内容,其中1234将是旧id之一。复制时,我想用melCode中的新id替换所有旧id
我可以用上面所示的游标循环来完成,但是当有一个大数据集时,它的速度非常慢。我也尝试了下面的代码,但如果melCode中有多个旧id,它将尝试多次更新同一行并抛出错误:
MERGE INTO dbo.mel b
USING @fieldNewOld a
ON b.fID = (select IdNew from @newForm) and b.melCode LIKE ('%_' + CONVERT(varchar(50), a.IdOld) + '%')
WHEN MATCHED THEN
UPDATE
SET b.melCode = REPLACE(b.melCode, '_' + CONVERT(varchar(50),a.IdOld), '_' + CONVERT(varchar(50),a.IdNew));
有没有办法以基于集合的方式实现这一点,或者我被光标循环的缓慢所困扰
示例数据:
@菲尔德纽奥尔德
IdOld | IdNew
1234 | 5678
1235 | 5679
1236 | 5680
melCode(所有这些将在一行中)
复制后,我希望melCode看起来像这样:
userok("My variable: " + myVar_5678)
myVar_5678 = "this is a test"
newVar_5680 = "here is some more data"
可以在更新中使用联接
UPDATE m
SET melCode = REPLACE(melCode, '_' + CONVERT(varchar(50),IdOld), '_' + CONVERT(varchar(50),fIdNew))
FROM dbo.mel m
JOIN @fieldNewOld fno ON m.melCode LIKE ('%_' + CONVERT(varchar(50), IdOld) + '%')
where fID = (select IdNew from @newForm) ;
这似乎在melCode中有一个复合值。我的建议是将该值拆分为2列或更多列,并将melCode作为计算列。考虑使用最终表格和表格变量的
JOIN
进行更新:
UPDATE m
SET m.melCode = REPLACE(m.melCode, '_' + CONVERT(varchar(50), f.IdOld),
'_' + CONVERT(varchar(50), f.IdNew))
FROM dbo.mel m
JOIN @fieldNewOld f
ON m.melCode LIKE ('%_' + CONVERT(varchar(50), f.IdOld) + '%')
JOIN @newForm n
ON m.fID = n.IdNew
由于您需要多次更新同一个文本,请考虑在一个迭代更新中运行上述代码,该更新遍历<代码>字段NeWordOrd < /Cord>IDS:< /P>中的行数。
DECLARE @Counter INT
DECLARE @ID_Count INT
SET @Counter = 0
SET @ID_Count = (SELECT COUNT(*) FROM @fieldNewOld)
WHILE @Counter <= @ID_Count
BEGIN
UPDATE m
SET m.melCode = REPLACE(m.melCode, '_' + CONVERT(varchar(50), f.IdOld),
'_' + CONVERT(varchar(50), f.IdNew))
FROM dbo.mel m
JOIN @fieldNewOld f
ON m.melCode LIKE ('%_' + CONVERT(varchar(50), f.IdOld) + '%')
JOIN @newForm n
ON m.fID = n.IdNew
SET @Counter += 1
END
DECLARE@Counter INT
声明@ID\u Count INT
设置@Counter=0
设置@ID\u Count=(从@fieldNewOld中选择Count(*)
而@Counter你可以使用加入。嗨,菲尔!请提供输入示例和所需输出/状态?@Cowthulhu示例输入和所需输出已添加,谢谢!通常,您可以(也应该)始终使用基于集合的逻辑,除非您在循环中调用另一个存储过程。即使如此,也只有在调用系统存储过程的情况下才应该这样做。注意之类的和通配符匹配<代码>%
将匹配一堆字符,(有趣的事实!)\u
将匹配一(一)个字符。所以,像“%\u1”
很可能不会做您认为它会做的事情。在转义字符中工作:类似“%[\]”
。。。但是要进行大量测试,以确保它按预期工作。根据我在上面输入的示例数据,您提供的代码只更新一个id,而不是多个id。因此,在上面的示例中,myVar_1234将更改为myVar_5678,但newVar_1236不会使用您提供的代码更改为newVar_5680。@Phil您从哪里得到这个想法?你说的不是真的。@LuisCazares我刚刚运行了代码,它只更新了一个变量。也许我错过了什么。我会再试一次。@Phil Parfait的代码或我的代码中没有任何内容会将更新的行限制为一行。@LuisCazares只有一行数据需要更新,所以这不是问题所在。问题在于,单行数据包含对多个id的多个引用,这些引用都需要更新以反映新id。使用提供的连接代码,这个userok(“我的变量:+myVar_1234)myVar_1234=”这是一个测试“newVar_1236=”这里还有一些数据“
变成了这个userok(“我的变量:+myVar_5678)myVar_5678=”这是一个测试“newVar_1236=”这里还有一些数据“
DECLARE @Counter INT
DECLARE @ID_Count INT
SET @Counter = 0
SET @ID_Count = (SELECT COUNT(*) FROM @fieldNewOld)
WHILE @Counter <= @ID_Count
BEGIN
UPDATE m
SET m.melCode = REPLACE(m.melCode, '_' + CONVERT(varchar(50), f.IdOld),
'_' + CONVERT(varchar(50), f.IdNew))
FROM dbo.mel m
JOIN @fieldNewOld f
ON m.melCode LIKE ('%_' + CONVERT(varchar(50), f.IdOld) + '%')
JOIN @newForm n
ON m.fID = n.IdNew
SET @Counter += 1
END