【问题标题】:How FOR XML PATH('') works when concatenating rows连接行时 FOR XML PATH('') 的工作原理
【发布时间】:2016-02-02 08:34:38
【问题描述】:

在连接 SQL Server 中的行时,FOR XML PATH ('') 子句如何工作?

我只想解释一下FOR XML PATH ('') 子句的工作原理...

【问题讨论】:

  • 这是一种滥用。正如它的名字所暗示的,这个特性的目的是生成XML。碰巧的是,某些特征组合意味着它可以用来连接字符串。
  • @Damien_The_Unbeliever 在 SQL Server 中有没有更好的方法?即更简洁,性能更好?
  • “有没有更好的方法” - 是的 - “在 SQL Server 中” - 不是真的。这是字符串操作,通常最好使用具有强大字符串操作功能的语言来完成。 T-SQL 不是其中之一。所以如果可能的话,把这个格式化/表示逻辑移出数据库。
  • @Damien_The_Unbeliever T-SQL 可以做到,但仅限于 Sybase SQL Anywhere (LIST())。事实上,许多(如果不是大多数)SQL 实现都可以做到这一点。 MySQL (group_concat())、Oracle (listagg())、PostgreSQL (string_agg())、DB2 (listagg()) SQLite (group_concat()) 和 Firebird (LIST()) 的最新版本。在 Postgres、Oracle 和我相信 DB2 中,这些函数也是分析函数,因此它们支持窗口化。虽然我同意它应该由应用程序在显示中处理,但报告创作软件在这方面通常非常不灵活。
  • @MartinSmith 哦,快!我没有看到。我对 SQL Server 最大的不满之一终于得到了解决。当 2016 年仅包含 string_splitstring_escape 时,我感到非常恼火。现在我只需要等到我们迁移到 SQL Server 2017,这有望在 2050 年之前的某个时间。

标签: sql-server tsql for-xml-path


【解决方案1】:

FOR XML PATH('xxx') 所做的是为结果集创建一个 XML 字符串,该字符串将每一行放入 <xxx></xxx> 元素中,并将行内的每个列值放入具有该列名称的元素中。

如果 PATH 为空(即PATH('')),它将在 XML 生成中省略行元素。如果列没有名称,则在 XML 生成中省略列元素。当 PATH 都为空且列没有名称时,它实际上变成了所有行的字符串连接。

运行以下语句以更好地了解该过程:

-- Each row is in a <beta></beta> element
-- Each column in that row in a <alfa></alfa> element (the column name)
SELECT
    alfa=','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('beta');

-- Since the PATH is empty, the rows are not put inside an element
-- Each column in that row is in a <alfa></alfa> element (the column name)
SELECT
    alfa=','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('');

-- Since the PATH is empty, the rows are not put inside an element
-- Since the column has no name it is not put inside an element     
SELECT
    ','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('');

-- This uses the STUFF function to remove the leading comma to get a proper comma-seperated list    
SELECT STUFF((
    SELECT
        ','+TABLE_SCHEMA + '.' + TABLE_NAME
    FROM
        INFORMATION_SCHEMA.TABLES
    FOR
        XML PATH('')
    ),1,1,''
) AS comma_seperated_list;

现在我听到您在问:当我只是从表中选择一列时,如何删除列名。有几种方法,按我的喜好排列:

  • XQuery 属性:SELECT [text()]=column_name ...
  • 使用子查询选择列值:SELECT (SELECT column_name) ...
  • 将该列转换为其类型:SELECT CAST(column_value AS &lt;TYPE of the column&gt;) ...

例子:

SELECT
    [text()]=TABLE_NAME
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('');

SELECT
    (SELECT TABLE_NAME)
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('');

SELECT
    CAST(TABLE_NAME AS SYSNAME)
FROM
    INFORMATION_SCHEMA.TABLES
FOR
    XML PATH('');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 2015-07-01
    • 1970-01-01
    • 2015-09-21
    • 2016-03-24
    • 2023-04-09
    相关资源
    最近更新 更多