sql >> Databáze >  >> RDS >> Sqlserver

Co tento dotaz dělá pro vytvoření seznamu SQL Server odděleného čárkami?

Nejjednodušším způsobem, jak to vysvětlit, je podívat se na to, jak FOR XML PATH funguje pro skutečné XML. Představte si jednoduchou tabulku Employee :

EmployeeID      Name
1               John Smith
2               Jane Doe

Můžete použít

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

To by vytvořilo XML následovně

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

Odebrání 'Zaměstnanec' z PATH odebere vnější xml tagy, takže tento dotaz:

SELECT  Name
FROM    Employee
FOR XML PATH ('')

By vytvořil

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

To, co potom děláte, není ideální, název sloupce 'data()' vynutí chybu SQL, protože se pokouší vytvořit značku xml, která není legální značkou, takže se vygeneruje následující chyba:

Název sloupce 'Data()' obsahuje neplatný identifikátor XML, jak vyžaduje FOR XML; '('(0x0028) je první chybný znak.

Korelovaný poddotaz tuto chybu skryje a pouze vygeneruje XML bez značek:

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

vytváří

John Smith Jane Doe

Potom nahrazujete mezery čárkami, což je docela samovysvětlující...

Na vašem místě bych dotaz mírně upravil:

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; 

Bez aliasu sloupce nebudou vytvořeny žádné xml tagy a přidání čárky do výběrového dotazu znamená, že jakákoli jména s mezerami nezpůsobí chyby,STUFF odstraní první čárku a mezeru.

DODATEK

Chcete-li upřesnit, co KM řekl v komentáři, protože se zdá, že to získává několik dalších zobrazení, správným způsobem, jak uniknout znakům XML, by bylo použít .value takto:

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. Tabulka historie SQL serveru – naplnit pomocí SP nebo Trigger?

  2. Průvodce návrhem databáze pro systém řízení zásob v MySQL

  3. Kontrola, zda je třeba aktualizovat sloupec bez LOB

  4. Co jsou zámky řádků, stránek a tabulek? A kdy jsou pořízeny?