我有一个表,其中每个记录都有一个Table_Name(表的名称)。然后,我使用Cursor选择与Cursor中的某些记录相关的所有表名。然后我为Cursor中的每个表名做一个WHILE来做一些工作。
我想知道是否可以在不使用光标的情况下解决此问题。
DECLARE tables_cursor CURSOR FAST_FORWARD FOR SELECT Table_Name FROM Some_Table WHERE ...
FETCH NEXT FROM tables_cursor INTO @Dynamic_Table_Name
WHILE @@FETCH_STATUS = 0
BEGIN
...
END
游标中的Foreach表名我执行动态SQL查询,如下所示:
SELECT @sql = '
UPDATE dbo.' + @Dynamic_Table_Name + '
SET ...'
EXEC sp_executesql @sql, @params, ...
我的问题是:是否可以避免使用Cursor来解决这个问题?
不幸的是,无法更改具有引用表的表名的设计,如果可以的话,我会立即做的。
答案 0 :(得分:1)
是的,您可以避开光标,但无法避免动态查询。
您可以创建一个查询,将所有连接在一起的动态查询作为单个字符串返回。这样你就可以在不使用循环的情况下执行它们,但这并不是更好......
如果无法更改数据库设计,则会遇到动态查询。
答案 1 :(得分:1)
嗯,您可以隐藏使用游标(使用未记录但广泛使用的)MS存储过程sp_MSforeachdb
(Google有很多示例);但是它在内部使用了一个光标,所以如果这是一个哲学上的反对意见,那么这并没有真正的帮助。
我不认为可以是一种基于集合的方式来做这种事情,因为每个表可能都有不同的关系结构。
答案 2 :(得分:1)
是,您可以在不使用游标的情况下解决此问题。相反,您需要引入新表,该表存储来自实际表的表名以及自动生成的id列。
查看以下示例查询
declare @test table (id int identity,tableName varchar(20))
insert into @test
select 'abc' union all
select '123' union all
select '345' union all
select 'sdf' union all
select 'uhyi'
而不是查询,您可以使用您的查询来填充表变量
insert into @test
SELECT Table_Name FROM Some_Table WHERE ...
和
--select * from @test
declare @cnt int
declare @incr int
select @cnt = count(id) from @test
set @incr = 1
while (@incr <= @cnt)
begin
select tableName from @test where id = @incr
set @incr =@incr + 1
end