在准备好的语句中使用游标进行更新
Posted
技术标签:
【中文标题】在准备好的语句中使用游标进行更新【英文标题】:Using cursor for update inside a prepared statement 【发布时间】:2018-08-05 23:08:44 【问题描述】:我在 JDBC 准备语句中使用了以下游标,如下所示:
DECLARE c CURSOR GLOBAL FORWARD_ONLY DYNAMIC SCROLL_LOCKS TYPE_WARNING
FOR
SELECT TxtPtr = TEXTPTR(PT.BODY), Src = N'ReplaceString',
Offset = PATINDEX(N'%[^A-Za-z0-9]SearchThis[^A-Za-z0-9]%', PT.BODY)
FROM dbo.BODYCONTENT AS PT
WHERE PT.BODY LIKE N'%[^A-Za-z0-9]SearchThis[^A-Za-z0-9]%';
OPEN c;
DECLARE @Ptr binary(16), @Src nvarchar(50), @Offset integer;
FETCH NEXT FROM c INTO @Ptr, @Src, @Offset;
WHILE @@FETCH_STATUS=0
BEGIN;
BEGIN TRANSACTION;
UPDATE dbo.BODYCONTENT SET BODY = ltrim(rtrim(replace
(replace(replace(N' ' + cast(BODY as nvarchar(max)) + N' ','
','<>'),'>' + @Offset + '<','>' + @Src+ '<'),'<>',' ')))
from dbo.BODYCONTENT
COMMIT TRANSACTION;
FETCH NEXT FROM c INTO @Ptr, @Src, @Offset;
END;CLOSE c; DEALLOCATE c;
当我直接在数据库中执行上述游标时,它只有在将@Src
和@Offset
的值明确指定为'>SearchThis<','>ReplaceString<'
时才有效
如何在查询中使用@Src
和@Offset
?
JDBC 准备好的语句:
String sql3 = "DECLARE c CURSOR GLOBAL FORWARD_ONLY DYNAMIC
SCROLL_LOCKS TYPE_WARNING FOR" +
" SELECT TxtPtr = TEXTPTR(PT.BODY), Src = N'+ ? + ',
Offset = PATINDEX(N'%[^A-Za-z0-9] + ? + [^A-Za-z0-9]%', PT.BODY)" +
" FROM dbo.BODYCONTENT AS PT" +
" WHERE PT.BODY LIKE N'%[^A-Za-z0-9]?[^A-Za-z0-9]%';" +
" OPEN c;" +
" DECLARE @Ptr binary(16), @Src nvarchar(50), @Offset
integer;" +
" FETCH NEXT FROM c INTO @Ptr, @Src, @Offset;" +
" WHILE @@FETCH_STATUS=0" +
" BEGIN" +
" BEGIN TRANSACTION;" +
" UPDATE dbo.BODYCONTENT SET BODY = ltrim(rtrim(replace(replace(replace(N' ' + cast(BODY as nvarchar(max)) + N' ',' ','<>'),'>' + @Offset +'<','>' + @Src + '<'),'<>',' '))) from dbo.BODYCONTENT" +
"COMMIT TRANSACTION;" +
"FETCH NEXT FROM c INTO @Ptr, @Src, @Offset;" +
"END;CLOSE c; DEALLOCATE c;";
pstmt = conn.prepareStatement(sql3);
pstmt.setNString(1, searchStr);
pstmt.setNString(2, replaceString);
pstmt.setNString(3, searchStr);
pstmt.executeUpdate();
我应该如何实现这个?
我认为问题在于我将?
提供给setNString
设置的参数。游标本身没有问题,游标适用于硬编码值。但我希望能够使用 setNString
或类似的东西从配置文件中传入 java 应用程序中的参数。
【问题讨论】:
首先,你应该摆脱你的光标。更新有点令人困惑,因为您对每一行都进行了更新,而不仅仅是游标中的那一行。但是,当您在 sql 数据库中工作时,您需要考虑基于集合,而不是基于程序。将查询重构为一个简单的update table set blah where blah
【参考方案1】:
不试图理解你所有的 patindex 并替换字符串(因为我的大脑爆炸了),它应该是一个简单的无光标更新语句,如下所示:
UPDATE dbo.BODYCONTENT SET BODY = ltrim(rtrim(replace
(replace(replace(N' ' + cast(BODY as nvarchar(max)) + N' ','
','<>'),'>' + PATINDEX(N'%[^A-Za-z0-9]SearchThis[^A-Za-z0-9]%', PT.BODY) + '<','>' + N'ReplaceString'+ '<'),'<>',' ')))
from dbo.BODYCONTENT
WHERE PT.BODY LIKE N'%[^A-Za-z0-9]SearchThis[^A-Za-z0-9]%';
【讨论】:
您好 TomC,感谢您的回复。但问题是我正在尝试使用参数化查询。当我对字符串“SearchThis”和“ReplaceString”进行硬编码时,我的光标工作得很好。但问题是当我尝试使用 setNString 或 setString 时,它不起作用。以上是关于在准备好的语句中使用游标进行更新的主要内容,如果未能解决你的问题,请参考以下文章
无法在准备好的 INSERT 语句中的 python mysql.connector 中使用 None (NULL) 值