想象一下以下架构:
create table tempdb..t1 (id int, name sysname);
create table tempdb..t2 (id int, name sysname);
create index IX1 on tempdb..t1 (id);
create index IX2 on tempdb..t2 (id);
现在我正在尝试编写索引定义脚本:
declare @stmt nvarchar(max) = '';
select @stmt += 'create index ' + ix.name + ' on ' + t.name
+ isnull(' where ' + ix.filter_definition, '') + char(13)
from tempdb.sys.tables t
join tempdb.sys.indexes ix on t.object_id = ix.object_id
where ix.type > 0 and t.name in ('t1','t2')
order by ix.name;
print @stmt;
我希望得到两个索引定义:
create index IX1 on t1
create index IX2 on t2
但只获得第二名。如果我删除order by
或isnull
部分,或添加top
语句,我会得到两个定义。
我错过了一些明显的东西吗?
答案 0 :(得分:0)
当您使用select将值放入标量变量时,只会在变量中放入一行。它不会将您的两行(或结果集大小)聚合成一行。
想象一下,你有一个变量是一个整数,你尝试为它分配700个不同的值,这是行不通的。尝试将两个字符串分配给同一个变量也是一样的。相反,只会使用其中一个值。
declare @i int;
SELECT @i = t.value
FROM myTable AS t
WHERE t.value between 1 and 700
SELECT @i
创建伪字符串连接聚合函数的一种好方法是使用FOR XML PATH的XML功能。 看看这个问题:How to concatenate results in T-SQL into column?
答案 1 :(得分:0)
我很惊讶这种行为是设计的。
总结来自Martin链接的信息:不要像这样进行连接。即使没有order by
,也无法保证工作。
要获得有保证的结果,请使用for xml
。
declare @stmt nvarchar(max) = '';
select @stmt = (select
'create index ' + ix.name + ' on ' + t.name
+ isnull(' where ' + ix.filter_definition, '') + char(10)
from tempdb.sys.tables t
join tempdb.sys.indexes ix on t.object_id = ix.object_id
where ix.type > 0 and t.name in ('t1','t2')
order by ix.name
for xml path(''));
print @stmt;
其他选项使用游标或SQLCLR。