2011-03-07 53 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 
相关问题