2011-03-07 5 views
1

SQL을 사용하여 문자열을 연결합니다.원본 테이블의 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'의 데이터 유형은 무엇입니까? 계획에 추가 캐스팅이 있다는 것을 의미하는 단일 바이트입니까? –

+0

Person.FirstName의 데이터 유형은 nvarchar (128) NOT NULL입니다. –

답변

3

문자열을 연결하는이 방법은 작동하지 않을 수도 있습니다. Microsoft는 "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

+0

@gbn - 아담 Machanic의 의견은 여기에있다. (http://sqlblog.com/blogs/adam_machanic/archive/2006) /07/12/rowset-string-concatenation-which-method-is-best.aspx). 왜 문서화되지 않은면을 사용한다고 생각합니까? –

+1

Dunno. SQL 유형에 의해 여기에서 여러 번 언급되는 것을 보았습니다. MVP 동료에게 그가 무엇을 파헤 치는지 볼 것을 요청했습니다. 흥미로운 의견. 업데이트 : http://www.projectdmx.com/tsql/rowconcatenate.aspx#BBXML – gbn

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 
관련 문제