sql >> Databasteknik >  >> RDS >> Sqlserver

Vad gör den här frågan för att skapa SQL Server med kommaavgränsad lista?

Det enklaste sättet att förklara det är att titta på hur FOR XML PATH fungerar för faktisk XML. Föreställ dig en enkel tabell Employee :

EmployeeID      Name
1               John Smith
2               Jane Doe

Du kan använda

SELECT  EmployeeID, Name
FROM    emp.Employee
FOR XML PATH ('Employee')

Detta skulle skapa XML enligt följande

<Employee>
    <EmployeeID>1</EmployeeID>
    <Name>John Smith</Name>
</Employee>
<Employee>
    <EmployeeID>2</EmployeeID>
    <Name>Jane Doe</Name>
</Employee>

Ta bort "Anställd" från PATH tar bort de yttre xml-taggarna så denna fråga:

SELECT  Name
FROM    Employee
FOR XML PATH ('')

Skulle skapa

    <Name>John Smith</Name>
    <Name>Jane Doe</Name>

Det du sedan gör är inte idealiskt, kolumnnamnet 'data()' tvingar fram ett sql-fel eftersom det försöker skapa en xml-tagg som inte är en laglig tagg, så följande fel genereras:

Kolumnnamnet 'Data()' innehåller en ogiltig XML-identifierare som krävs av FOR XML; '('(0x0028) är det första tecknet som är fel.

Den korrelerade underfrågan döljer detta fel och genererar bara XML utan taggar:

SELECT  Name AS [Data()]
FROM    Employee
FOR XML PATH ('')

skapar

John Smith Jane Doe

Du ersätter då mellanslag med kommatecken, ganska självförklarande...

Om jag var du skulle jag anpassa frågan något:

SELECT  E1.deptno, 
        STUFF(( SELECT  ', ' + E2.ename 
                FROM    emp AS e2 
                WHERE   e1.deptno = e2.DEPTNO 
                FOR XML PATH('')
            ), 1, 2, '') 
FROM    EMP AS e1 
GROUP BY DEPTNO; 

Att inte ha något kolumnalias kommer att innebära att inga xml-taggar skapas, och att lägga till kommatecken i urvalsfrågan innebär att alla namn med mellanslag inte orsakar fel,STUFF kommer att ta bort det första kommatecken och mellanslag.

TILLÄGG

För att utveckla vad KM har sagt i en kommentar, eftersom detta verkar få några fler visningar, skulle det korrekta sättet att undvika XML-tecken vara att använda .value enligt följande:

SELECT  E1.deptno, 
        STUFF(( SELECT  ', ' + E2.ename 
                FROM    emp AS e2 
                WHERE   e1.deptno = e2.DEPTNO 
                FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') 
FROM    EMP AS e1 
GROUP BY DEPTNO; 


  1. Att använda if(isset($_POST['submit'])) för att inte visa eko när skriptet är öppet fungerar inte

  2. UUID-prestanda i MySQL?

  3. NULL komplexitet – del 1

  4. 3 sätt att få dagnamnet från ett datum i MariaDB