2011-03-07 26 views
1

我使用SQL連接字符串在一起。是什麼ISNULL之間的臨時表VS ISNULL上原始表的區別?

此語句的工作原理:

DECLARE @FirstNamesString nvarchar(256) 
SELECT 
    @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName 
FROM 
    Person p 
ORDER BY 
    p.SortOrder 

而且我得到第一個名稱列表,如:

Name1, Name2, Name3

現在,我想在一個可能爲null的姓氏字段中添加對於這些人。我想下面的SQL,但我只得到列表中的最後一個項目(Name3):

DECLARE @FirstNamesString nvarchar(256) 
SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '') 
FROM 
    Person p 
ORDER BY 
    p.SortOrder 

,但如果我第一次插入所有這些名字到一個臨時表,然後一切按預期工作:

CREATE TABLE #Person2 
(
    FirstName nvarchar(128) NOT NULL 
    ,LastName nvarchar(256) NULL 
    ,SortOrder int NOT NULL 
) 

INSERT INTO #Person2 (FirstName, LastName, SortOrder) (
    SELECT p.FirstName, p.LastName, p.SortOrder FROM Person p) 

DECLARE @FirstNamesString nvarchar(256) 

SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '') 
FROM 
    #Person2 p 
ORDER BY 
    p.SortOrder 

DROP TABLE #Person2 

那麼究竟是什麼上述對原始表和對臨時表的一個語句之間的區別?該臨時表的路由的工作原理,我想用那個,但我很好奇......我缺少什麼嗎?

更新了可能的解決方案

@Martin's answer但字符串的連接是不能保證工作。因此,一個解決方案是將姓氏之前,首先選擇名字的列表中插入到臨時表:

CREATE TABLE #Person2 
(
    FirstName nvarchar(256) NOT NULL 
    ,SortOrder int NOT NULL 
) 

INSERT INTO #Person2 (FirstName, SortOrder) (
    SELECT p.FirstName + ISNULL(' ' + p.LastName, ''), p.SortOrder 
    FROM Person p 

) 

DECLARE @FirstNamesString nvarchar(256) 

SELECT 
    @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName 
FROM 
    #Person2 p 
ORDER BY 
    p.SortOrder ASC 
+0

「p.FirstName」的數據類型是什麼?那個單字節意味着計劃中有一個額外的'cast'嗎? – 2011-03-07 12:42:06

+0

數據類型Person.FirstName的數據類型爲nvarchar(128)NOT NULL。 – 2011-03-07 13:45:27

回答

3

這種方法來連接字符串不能保證正常工作。微軟稱"The correct behavior for an aggregate concatenation query is undefined."。如果計算標量在計劃中出現錯誤的地方,它將會失敗。你能展示兩種計劃嗎?

您當然可以/應該只使用XML PATH來連接字符串,因爲您在SQL Server 2008上,並且這是 記錄的工作。 當前版本可靠。

例子:

DECLARE @FirstNamesString nvarchar(256) 

SELECT @FirstNamesString = (
SELECT CASE 
     WHEN ROW_NUMBER() OVER (ORDER BY (p.SortOrder)) = 1 THEN '' 
     ELSE ',' 
     END + p.FirstName + ISNULL(' ' + p.LastName, '') 
FROM Person p 
ORDER BY p.SortOrder 
FOR XML PATH(''), TYPE 

).value('.[1]','nvarchar(256)') 


PRINT @FirstNamesString 
+0

「這是記錄在案的工作。」?你有參考嗎?我一直認爲這是發生在我們想要做的事情上的內部事物... – gbn 2011-03-07 12:12:53

+0

@gbn - 傳遞了一點信息,但[Adam Machanic的評論在這裏](http://sqlblog.com/blogs/adam_machanic/archive/2006 /07/12/rowset-string-concatenation-which-method-is-best.aspx)。爲什麼您認爲它使用了無證方面? – 2011-03-07 12:16:46

+1

鄧諾。我在這裏看到過幾次SQL類型。我已經要求MVP的同事看看他能挖掘出什麼。但有趣的評論。更新:http://www.projectdmx.com/tsql/rowconcatenate.aspx#BBXML – gbn 2011-03-07 12:20:35

0

我想這和它工作正常。但可變引擎確實不能保證工作。 (並且它是無證的)

create table Person(FirstName nvarchar(10), LastName nvarchar(20), SortOrder int) 

insert into Person 
VALUES ('Pers1', 'Last1', 1), 
     ('Pers2', 'Last2', 2), 
     ('Pers3', 'Last3', 3), 
     ('Pers4', 'Last4', 4), 
     ('Pers5', NULL, 5) 

DECLARE @FirstNamesString nvarchar(256) 
SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '') 
FROM 
    Person p 
ORDER BY 
    p.SortOrder 

print @FirstNamesString 
相關問題