В чем разница между isnull на временной таблице и isnull на исходной таблице? - PullRequest
1 голос
/ 07 марта 2011

Я использую SQL для объединения строк.

Это утверждение работает:

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

И я получаю список имен, таких как:

Name1, Name2, Name3

Теперь я хочу добавить в возможно нулевое поле фамилии для каждого из этих людей. Я попробовал 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

Так в чем же разница между приведенным выше утверждением относительно исходной таблицы и приведенным для временной таблицы? Маршрут временных таблиц работает, и я собираюсь его использовать, но мне очень любопытно ... что мне здесь не хватает?

ОБНОВЛЕНО ВОЗМОЖНЫМ РЕШЕНИЕМ

См. @ ответ Мартина , но конкатенация строк не гарантируется. Таким образом, решение заключается в том, чтобы сначала вставить фамилию во временную таблицу до выбора списка имен:

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

Ответы [ 2 ]

3 голосов
/ 07 марта 2011

Этот подход к объединению строк не гарантированно работает.Microsoft говорит «Правильное поведение для запроса совокупной конкатенации не определено». .Он потерпит неудачу, если вычисленный скаляр окажется в неправильном месте в плане.Можете ли вы показать оба плана?

Конечно, вы можете / должны просто использовать 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 голосов
/ 07 марта 2011

Я попробовал это, и он отлично работает.Но переменный двигатель действительно не гарантирует работу.(и без документов)

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...