首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Server索引(物化)视图中创建嵌套XML

问在Server索引(物化)视图中创建嵌套XML
EN

Database Administration用户
提问于 2015-04-24 00:34:25
回答 1查看 1.5K关注 0票数 3

此页面https://msdn.microsoft.com/en-us/library/ms188276.aspx表示,如果需要嵌套XML (即XML ),则需要设置如下查询:

代码语言:javascript
复制
SELECT Col1, 
       Col2, 
       ( SELECT Col3, Col4 
        FROM  T2
        WHERE T2.Col = T1.Col
        ...
        FOR XML AUTO, TYPE )
FROM T1
WHERE ...
FOR XML AUTO, TYPE;

(使用子查询)

这完全不符合索引视图的要求(不允许子查询)。

不管怎么说,这两个特性是有联系的吗?(有一个有XML树的索引视图吗?)

我的问题是:如何在不使用任何子查询或联合的情况下,从许多表创建XML树(即嵌套XML节点)。(因此它将使用Server索引视图。)

FYI:不确定是否重要,但我的特定查询有超过10个级别的xml树(从一堆不同的表中提取)。

EN

回答 1

Database Administration用户

回答已采纳

发布于 2017-05-19 20:13:38

简短的回答:你不能。

较长的答覆:

这里发生了一些事情。

首先,您可能低估了XML AUTO的威力。它将提供一定数量的嵌套“自动”。实际上,不需要嵌套XML生成就可以处理所提供的示例。

让我们制作一些测试表和数据:

代码语言:javascript
复制
USE tempdb;

DROP TABLE IF EXISTS T1;
DROP TABLE IF EXISTS T2;

CREATE TABLE T1
(
    Col1 int,
    Col2 varchar(50),
    [Col] char(1)
);

CREATE TABLE T2
(
    [Col] char(1),
    Col3 varchar(50),
    Col4 varchar(50)
);

INSERT INTO T1 (Col1, Col2, [Col]) VALUES
    (1, 'Test1', 'A'), (2, 'Test2', 'B');
INSERT INTO T2 ([Col], Col3, Col4) VALUES
    ('A','1x','1y'), ('A','2x','2y'), ('B','3x','3y'), ('B','4x','4y'), ('B','5x','5y');

您的查询:

代码语言:javascript
复制
SELECT
    Col1,
    Col2,
    (
        SELECT      Col3, Col4
        FROM        T2
        WHERE       T2.Col = T1.Col
        FOR XML AUTO, TYPE
    )
FROM        T1
FOR XML AUTO, TYPE;

产生的结果与没有嵌套的结果相同:

代码语言:javascript
复制
SELECT
    Col1,
    Col2,
    Col3,
    Col4
FROM        T1
JOIN        T2
ON          T2.Col = T1.Col
FOR XML AUTO, TYPE;

它们都产生:

代码语言:javascript
复制
<T1 Col1="1" Col2="Test1">
  <T2 Col3="1x" Col4="1y" />
  <T2 Col3="2x" Col4="2y" />
</T1>
<T1 Col1="2" Col2="Test2">
  <T2 Col3="3x" Col4="3y" />
  <T2 Col3="4x" Col4="4y" />
  <T2 Col3="5x" Col4="5y" />
</T1>

(如果您有更复杂的或自定义的嵌套需求,则会发生故障。)

不管这个特定的例子如何,我认为没有一种有效的方法可以将(动态) XML放到索引视图中。

首先,“索引视图”实际上是一个具有唯一聚集索引的视图。不能在XML列上创建“正常”索引.

假设你试着:

代码语言:javascript
复制
CREATE TABLE T3
(
    x xml
);
CREATE UNIQUE CLUSTERED INDEX IX_T3 ON T3 (x);
GO

您将得到一个错误:

1977年Msg,第16级,状态1,第73行无法在表'T3‘上创建索引'IX_T3’。只能在XML列'x‘上创建XML索引。

XML索引呢?嗯:

不能在视图中的XML列、带有xml列的表值变量或xml类型变量上创建xml索引(主索引或辅助索引)。

创建XML索引(Transact-SQL)

因此,为了使用视图实现XML,它不能是唯一的列。您需要一个“普通”列来创建唯一的聚集索引。获取普通列的一种方法是使用子查询创建XML。但正如你所指出的,如果你试着这样做:

代码语言:javascript
复制
CREATE VIEW V1
(
    n,
    x
)
WITH SCHEMABINDING
AS
SELECT 
    1,
    (
        SELECT 'Test' AS 'Col'
        FOR XML PATH, TYPE
    )
GO

CREATE UNIQUE CLUSTERED INDEX IX_V1 ON V1 (n);
GO

您将得到以下错误:

Msg 10127、级别16、状态1、行83不能在视图"tempdb.dbo.V1“上创建索引,因为它包含一个或多个子查询。考虑将视图更改为只使用联接而不是子查询。或者,考虑不对此视图进行索引。

您可能认为可以通过创建没有子查询的外部视图来欺骗,调用原始视图。但如果你试着:

代码语言:javascript
复制
CREATE VIEW V2
(
    n,
    x
)
WITH SCHEMABINDING
AS
SELECT
    n,
    x
FROM    dbo.V1;
GO

CREATE UNIQUE CLUSTERED INDEX IX_V2 ON V2(n);
GO

您将得到一个错误:

MSG1937、级别16、状态1、第98行不能在视图'tempdb.dbo.V2‘上创建索引,因为它引用了另一个视图'dbo.V1’。考虑在索引视图定义中手动扩展引用视图的定义。

因此,您不能嵌套这些视图,也不能使用子查询。您也不能使用应用运算符,因此您不能使用表值用户定义函数(也不能有效地使用nodes XML函数)。

但是你可以使用确定性标量值函数。因此,您可以构造一些基本的XML。例如:

代码语言:javascript
复制
CREATE FUNCTION F1
(
    @Col1 int,
    @Col2 varchar(50)
)
RETURNS xml
WITH SCHEMABINDING
AS
BEGIN
    RETURN
        (
            SELECT
                @Col1,
                @Col2
            FOR XML PATH(''), TYPE
        )
END
GO

CREATE VIEW V3
(
    n,
    x
)
WITH SCHEMABINDING
AS
SELECT
    Col1,
    dbo.F1(T1.Col1, T1.Col2)
FROM    dbo.T1 AS T1;
GO

CREATE UNIQUE CLUSTERED INDEX IX_V3 ON V3(n);
GO

虽然您可以在函数中创建复杂的、多层次的XML,但是函数不能引用任何表(否则它不会是确定性的)。例如,这是:

代码语言:javascript
复制
CREATE FUNCTION F2
(
    @Col1 int,
    @Col2 varchar(50),
    @Col char(1)
)
RETURNS xml
WITH SCHEMABINDING
AS
BEGIN
    RETURN
        (
            SELECT
                @Col1 AS Col1,
                @Col2 AS Col2,
                (
                    SELECT      Col3, Col4
                    FROM        dbo.T2 AS T2
                    WHERE       T2.Col = @Col
                    FOR XML AUTO, TYPE
                )
            FOR XML PATH, TYPE
        )
END
GO

CREATE VIEW V4
(
    n,
    x
)
WITH SCHEMABINDING
AS
SELECT
    Col1,
    dbo.F2(T1.Col1, T1.Col2, T1.Col)
FROM    dbo.T1 AS T1;
GO

CREATE UNIQUE CLUSTERED INDEX IX_V4 ON V4(n);
GO

导致此错误:

Msg 10133、级别16、状态1、第181行不能在视图"tempdb.dbo.V4“上创建索引,因为视图引用的函数"dbo.F2”执行用户或系统数据访问。

因此,该函数无法获取所需的信息。它必须得到信息。而且,我根本没有办法(我可以想到)从多个行收集数据,并将其提供给函数。可以提供要操作的确定性函数XML,但如果没有子查询,则无法创建基本XML。

因此,简而言之,我不认为有任何方法使用索引视图来物化XML,因为XML包含来自任何表中多行的数据。

票数 11
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/98721

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档