2013-04-04 123 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。