繁体   English   中英

从插入到选择查询中的单行中插入多行

[英]Insert multiple rows from a single row inside an insert into select query

我有以下架构(更为复杂的版本):

CREATE TABLE Messages (
    ItemId INT IDENTITY PRIMARY KEY,
    Name VARCHAR(20) NOT NULL,
    DeliveryType INT NOT NULL
);

CREATE TABLE NotificationsQueue (
    ItemId INT NOT NULL,
    DeliveryType INT NOT NULL
);

DeliveryType的可能值为:

0 -> none
1 -> mail
2 -> email
3 -> both

现在,在“消息”表中有一些条目:

INSERT INTO Messages(Name, DeliveryType) Values
('Test0', 0),
('Test1', 1),
('Test2', 2),
('Test3', 3)

我需要像这样填充NotificationsQueue表:

  • 当DeliveryType = 0时,请勿插入任何内容
  • 当DeliveryType = 1或DeliveryType = 2时,插入一个元组:(ItemId,DeliveryType)
  • 当DeliveryType = 3时,插入两个元组:(ItemId,1),(ItemId,2)

我这样做的尝试导致了以下两个查询:

INSERT INTO NotificationsQueue (ItemId, DeliveryType) SELECT ItemId, 1 AS DeliveryType FROM Messages WHERE DeliveryType IN (1, 3)
INSERT INTO NotificationsQueue (ItemId, DeliveryType) SELECT ItemId, 2 AS DeliveryType FROM Messages WHERE DeliveryType IN (2, 3)

即使此方法可行,但实际上插入操作的select语句要复杂得多,所以我想知道是否有任何好的方法可以将它们合并到单个查询中,以避免重复。

PS:不允许更改架构或在“ Messages表中添加重复项。

如果可以使用触发器,则可以执行此操作

CREATE TRIGGER dbo.Messages_Inserted ON dbo.[Messages]
    FOR INSERT
AS
    INSERT INTO dbo.[NotificationsQueue]
            ( ItemId
            ,DeliveryType
            )
            SELECT ItemId
                   ,1
                FROM INSERTED
                WHERE DeliveryType IN ( 1, 3 )
            UNION ALL
            SELECT ItemId
                   ,2
                FROM INSERTED
                WHERE DeliveryType IN ( 2, 3 )
GO

INSERT INTO dbo.[Messages](Name, DeliveryType) Values
('Test0', 0),
('Test1', 1),
('Test2', 2),
('Test3', 3)

SELECT * FROM dbo.[Messages]
SELECT * FROM dbo.NotificationsQueue

如果您只想一次选择所有内容,则可以创建一个查找表来转换类型,例如

;WITH cte AS (SELECT * FROM (VALUES (1,1),(2,2),(3,1),(3,2)) a(DeliveryType,type)) 
SELECT ItemId, t.type AS DeliveryType 
FROM Messages m
INNER JOIN    cte t
    ON t.DeliveryType = m.DeliveryType 

也许是这样的:

INSERT INTO NotificationsQueue (ItemId, DeliveryType) 
select itemid, case when deliverytype = 3 then n else deliverytype end
from messages
inner join (values(1), (2)) x(n) on n <= case when deliverytype=1 then 2 else deliverytype end -1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM