插入内侧交叉应用

时间:2014-09-24 17:41:19

标签: sql sql-server tsql

    SELECT DISTINCT CODE
    FROM   T1
    CROSS APPLY 
    (
        INSERT  INTO T4(TEXT1, TEXT2, TEXT3)
        SELECT  T2.TEXT1, T2.TEXT2, T3.TEXT3
        FROM    T2,
                T3
        WHERE   T2.ID = T3.ID
        AND     T2.CODE = T1.CODE
    ) AS T

使用执行此查询时,我收到此错误:

  

嵌套的INSERT,UPDATE,DELETE或MERGE语句必须具有OUTPUT子句。

我做错了什么?

修改

我计划实现的是模拟WHILE..LOOP。 循环遍历T1中的所有CODE并为每个CODE获取T2和T3的TEXT字段(将它们与ID连接)并将它们插入表T4。

我试图通过CODE分隔插入,因为两个表都有大量数据,我试图提高性能(可能?!)

2 个答案:

答案 0 :(得分:2)

你无法做你想做的事情。语言不允许你。为了设置舞台,我创建了以下3个表

SET NOCOUNT ON;
CREATE TABLE dbo.Final
(
    ID int IDENTITY(1,1) NOT NULL
,   text1 varchar(50) NOT NULL
,   text2 varchar(50) NOT NULL
,   text3 varchar(50) NOT NULL
);

CREATE TABLE dbo.Chain
(
    ID int NOT NULL
);

CREATE TABLE dbo.Chained
(
    ID int NOT NULL
,   Foo int NOT NULL
);

为了演示OUTPUT子句的位置,我们将插入4行并查看漂亮的INSERTED虚拟表和相关的ID值。

-- Works
    INSERT INTO
        dbo.Final
    (
        text1
    ,   text2
    ,   text3
    )
    OUTPUT
        INSERTED.*
    SELECT
        D.t1
    ,   D.t2
    ,   D.t3    
    FROM
    (
        VALUES
            ('A', 'B', 'C')
        ,   ('D', 'B', 'C')
        ,   ('G', 'B', 'C')
        ,   ('J', 'B', 'C')
    ) D (t1,t2,t3);

现在,如果我执行以下语句,它将正常工作。但是,如果我忽略INSERT只是为了直观地检查我想要放入表中的内容,SQL Server将引发以下错误

  

SELECT语句中不允许嵌套的INSERT,UPDATE,DELETE或MERGE语句,该语句不是INSERT语句的直接行源。

-- Comment out the insert portion to generate
-- A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed in a SELECT statement that is not the immediate source of rows for an INSERT statement.
INSERT INTO
    dbo.Chain
(
    ID
)
SELECT
    X.ID
FROM
(
    INSERT INTO
        dbo.Final
    (
        text1
    ,   text2
    ,   text3
    )
    OUTPUT
        INSERTED.*
    SELECT
        D.t1
    ,   D.t2
    ,   D.t3    
    FROM
    (
        VALUES
            ('A', 'B', 'C')
        ,   ('D', 'B', 'C')
        ,   ('G', 'B', 'C')
        ,   ('J', 'B', 'C')
    ) D (t1,t2,t3)
) x

但是,你想要加倍努力并申请,或者用其他东西加入那个虚拟表的结果,而且不会飞。

  

JOIN或APPLY运算符的任何一侧都不允许嵌套的INSERT,UPDATE,DELETE或MERGE语句。

我认为它只是一个复杂程度太多了。

-- Now, try the same bit except we use the derived table as a JOIN/APPLY
-- Can't fix what's not supported 
-- A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed on either side of a JOIN or APPLY operator.
INSERT INTO
    dbo.Chained
(
    ID
,   Foo
)
SELECT
    X.ID
,   D.foo
FROM
(
    VALUES
    (1)
) D(Foo)
CROSS APPLY
(
    INSERT INTO
        dbo.Final
    (
        text1
    ,   text2
    ,   text3
    )
    OUTPUT
        INSERTED.*
    SELECT
        D.t1
    ,   D.t2
    ,   D.t3    
    FROM
    (
        VALUES
            ('A', 'B', 'C')
        ,   ('D', 'B', 'C')
        ,   ('G', 'B', 'C')
        ,   ('J', 'B', 'C')
    ) D (t1,t2,t3)
) x;

如果你真的需要这样的东西,那么你必须把它分解成单独的陈述。

答案 1 :(得分:2)

有点猜测

INSERT  INTO FINAL (TEXT1   , TEXT2   , TEXT3)
SELECT  DISTINCT    T2.TEXT1, T2.TEXT2, T3.TEXT3
  FROM  T1
  JOIN  T2
   on   T2.ID = T1.ID
  JOIN  T3
    on  T3.VALUE = T2.VALUE