是否有可能以某种方式为select的每一行执行一些代码而不使用游标?
在我的情况下: 我有一个临时表来存储一个复杂脚本的数据。最后,我想要将此表的某些信息(受某些条件限制)提供给输出。
目前我正在使用带有select的游标来限制表的行。在这个游标中我正在使用
print '...'
生成输出。
必须有一种更简单的方法来做这些事情......
编辑:
create table #tmpAttributes(AttributeId uniqueidentifier, Value float, ValueString nvarchar(max), ActionId uniqueidentifier)
insert into #tmpAttributes (AttributeId, Value, ValueString, ActionId)
select ID,..... -- in this select i'm doing some value conversions, if conversion is not possible i'm using -1
insert into ActionAttribute (ActionDefinitionID, Discriminator, ID, ReferredActionID, ValueDate, ValueListID, ValueMoney, ValueString, ValueUserID)
select @defId, 'ActionAttributeMoneyEntity', NEWID(), ActionId, null, null, Value, null, null from #tmpAttributes
-- afterwards there is this cursor where I'm printint all rows where Value = -1
答案 0 :(得分:20)
对结果集中的每一行执行print语句几乎需要一个游标或类似于此的方法
declare @id int, @stuff varchar(20)
declare @tmp table
(
id int not null
, stuff varchar(20)
primary key(id)
)
insert @tmp
select id, stuff from mastertable
where condition1 > condition2
select top 1 @id=id, @stuff=stuff from @tmp
while (@@rowcount > 0)
begin
print @stuff
delete from @tmp where id=@id
select top 1 @id=id, @stuff=stuff from @tmp
end
你仍在循环每一行,但你避免使用光标。由于您使用表var而不是游标,因此可以避免表锁定,但这不一定是更好的方法。您可以通过各种可能的方式逐行处理,例如添加“已处理的列”或对所有选定的行进行编号1..n并根据rownumber进行迭代
如果可以执行基于集合的操作,则只能逐行处理。您的问题中没有足够的信息来确定在TSQL中是否可以避免这种情况
现在,编写CLR proc可能会更灵活,因为您拥有更丰富的编程模型,并且在CLR proc中循环遍历结果集的每一行的开销很小。对于数据库从TSQL中的每一行调用的每一行,从CLR proc进行数据库调用
编辑 - 我看到有人已经添加了一种可能的方法将打印语句转换为面向集合的操作。即。
declare @msg varchar(max)
select @msg = ''
select msg = @msg + stuff
from mastertable where condition1 > condition2
print @msg
这是可以的,实际上是我在执行set操作时所指的最佳方式。在可能的情况下,始终首选基于集合的操作。它可能并不明显,但如果涉及很多行,字符串连接在这个例子中也会变得很慢。
我说使用temp var可以避免表锁定。这并不正确,因为sql server会将临时变量写入tempdb中的表。我真正的意思是你避免锁定生产表,因为你保证是这个表的唯一用户,你不会竞争并发访问。
我也没有试图对此进行优化。例如,内部循环可以跟踪id和where条件变为id> @id(您还需要在id上定义主键)。由于临时表在每次循环迭代期间都没有更新,我希望它更快。
答案 1 :(得分:8)
我认为您需要提供更多详细信息,但您可能正在寻找类似的内容:
declare @msg varchar(max)='';
select @msg = @msg + 'Output line: ' + ColumnA + ' -- ' + 'ColumnB' + char(13)+char(10)
from #temp
where ...
;
print @msg;