使用 T-SQL,是否可以拆分结果集或表,然后插入到两个不同的临时表中?

SQL*_*SQL 3 sql-server t-sql except

我有一张保存付款数据的表。我想将以拒绝状态结束的订单插入#tmp_Declined。然后,我想将最初被拒绝但在使用替代付款方式时获得授权的付款插入 #tmp_Authorized。

我可以使用 2 个 select into 语句来做到这一点,其中 where 子句略有不同,但使用相同的基表。

我考虑了一个类似下面的例子:

select *
into #tmp_Declined
from Payments

except

select *
from Payments 
where WasOrginallyDeclined = 1 
and MostRecentPaymentAccepted = 1 
Run Code Online (Sandbox Code Playgroud)

这种方法虽然仍然会在某个时间填充一个临时表。是否有保留字或查询“技巧”将插入#tmpA 中满足条件,然后插入#tmpB 中未插入#tmpA 中的任何内容?

我希望能够通过一个事务写入 2 个表。

Joe*_*ish 5

您所描述的功能有时称为多表插入。Oracle 是一种实现它的RDBMS 。它没有在 SQL Server 中实现。

如果您只需要通过一次数据来拆分数据,您有一些解决方法,但所有这些都会增加复杂性并产生其他负面影响。您可以定义一个分区堆并插入到该堆中。分区列将是定义目标表的 0/1 计算值。您基本上可以免费将堆中的 switch 分区到两个单独的表中。总的来说,这需要在插入之前对数据进行排序。

您可以定义一个分区视图,将您的数据插入该视图,然后删除该视图。分区视图的要求似乎不太适合您的场景。除其他事项外,您需要在包含确定目标表的计算列的两个目标表上使用主键。插入数据的查询计划可能看起来非常丑陋(尽管在 SSMS 17.4 中每个查询计划看起来都非常漂亮):

在此处输入图片说明

第三种选择是INSTEAD OF INSERT在目标表上定义触发器。触发器代码可以将行发送到正确的表。正如您可能想象的那样,这有一些开销。

如果要求只是在单个事务中插入数据,您可以使用显式事务和两个INSERT查询来实现。我只会否定该WHERE子句而不是加入同一个表。只要确保您正确处理 NULL。示例代码:

BEGIN TRANSACTION;

INSERT INTO #tmp_Declined
select *
from Payments 
where NOT (WasOrginallyDeclined = 1 and MostRecentPaymentAccepted = 1);

INSERT INTO #tmp_not_Declined
select *
from Payments 
where WasOrginallyDeclined = 1 and MostRecentPaymentAccepted = 1;

COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)


ype*_*eᵀᴹ 5

是否有保留字或查询“技巧”将插入#tmpA 中满足条件,然后插入#tmpB 中未插入#tmpA 中的任何内容?

是的,这很简单:

BEGIN TRANSACTION;

INSERT INTO #tmpA (...)
    SELECT...
    FROM Payments
    WHERE <some_condition> ;

INSERT INTO #tmpB (...)
    SELECT ...                 -- same as above,
    FROM Payments              -- no WHERE or a different one
    EXCEPT
    SELECT ...                 -- but don't insert
    FROM #tmpA ;               -- whatever went into tmpA

COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)