我有一个表(100+)表,所有表都包含两个字段
RowChanged bit
ChangedFields bit
现在,发生了一个错误,其中一些条目的RowChanged = 1,而ChangedFields为空。因此,我需要通过这些并设置RowChanged = 0,其中ChangedFields为空。
我已通过以下光标实现此目的。
BEGIN TRANSACTION
USE DatabaseName --Database name to clean
DECLARE @Table_Name VARCHAR(50)
DECLARE @Query VARCHAR(250)
DECLARE Table_Cursor CURSOR FOR SELECT Name FROM sys.tables;
DECLARE @Affected_Rows INTEGER = 0
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO @Table_Name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Query = 'Update '+@Table_Name+' Set RowChanged = 0 Where RowChanged = 1 And (LEN(RTRIM(CONVERT(NVARCHAR(100), ChangedFields))) = 0 OR ChangedFields IS NULL)'
EXEC (@Query)
SET @Affected_Rows = @Affected_Rows + COALESCE(@@ROWCOUNT, 0)
FETCH NEXT FROM Table_Cursor INTO @Table_Name
END
SELECT @Affected_Rows AS Affected_Rows
CLOSE Table_Cursor
DEALLOCATE Table_Cursor
ROLLBACK --Change to COMMIT in order to save changes
虽然这确实有效,但我对使用游标存在遗传厌恶。我也刚刚了解到,在很多情况下,Apply可以实现Cursors在2005年之前所做的事情。
我需要做的是遍历数据库中的所有表并检查RowChanged = 1和ChangedFields的条件,如''或NULL。
我试过用TVF来解决这个问题,但事实并非如此。虽然我可以在一个表中执行操作,但是从sys.tables获取列表并在几个表上执行某些操作却让我望而却步。
答案 0 :(得分:2)
您可以使用while循环语句替换光标。尝试使用如下所示的语句来获得所需的o / p。
select name into #table from sys.tables
while (select count(*) from #table)>0
begin
set rowcount 1
select @Table_Name = name from sys.tables
set rowcount 0
.......
.......
delete from #table where name = @Table_Name
end
以上代码段来自sybase,您可能需要对语法进行微小修改。我希望有所帮助。
答案 1 :(得分:1)
declare @stmt nvarchar(max)
select
@stmt =
isnull(@stmt + nchar(13) + nchar(10), '') +
'update '+ name +' set RowChanged = 0 Where RowChanged = 1 And (LEN(RTRIM(CONVERT(NVARCHAR(100), ChangedFields))) = 0 OR ChangedFields IS NULL)'
from sys.tables
print @stmt
sp_executesql @stmt = @stmt
还有未记录的存储过程sp_MSforeachtable
- SQL Server sp_msforeachtable usage to select only those tables which meet some condition。实际上,我从未在工作中使用过它,所以只是为了获取信息。