2013-04-04 127 views
0

想象一下下面的模式:意外的字符串连接结果

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 byisnull部分,或者添加top语句,我会得到两个定义。

我错过了一些明显的东西吗?

+3

这种连接方式不能保证能正常工作。参见[nvarchar的级联/指数/为nvarchar(最大)无法解释的行为]的可能重复(http://stackoverflow.com/questions/15138593/nvarchar-concatenation-index-nvarcharmax-inexplicable-behavior) – 2013-04-04 12:29:11

回答

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?

+0

聚集作品,如果我删除'秩序由'条款。但无法保证正确的结果。查看Martin的链接。 – Aryadev 2013-04-04 14:10:52

+1

我想我需要阅读连接。我认为这根本不适用于2008 R2。 – 2013-04-04 18:57:09

0

我大吃一惊这是行为设计​​。

要总结马丁链接的信息:不要做这样的连接。即使没有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。