【发布时间】:2019-07-31 09:45:24
【问题描述】:
现状
-
DataMessages.SenderID是一个 FK,以DataUser.UserID为参考 -
Data_UserGroup.UserID是一个 FK,以DataUser.UserID为参考 -
DataMessageRecipient.RecipID是一个 FK,以DataUser.UserID为参考 -
DataMessageRecipient.DestID是一个 FK,以DataUser.DestID为参考 -
DataMessageRecipient.MssgID是一个 FK,以DataMessages.ID为参考 -
DataMessages.ID和DataMessageRecipient.EntryID是IDENTITY()列
还有这个AFTER INSERT dbo.DataMessages 表上的触发器
CREATE TRIGGER OnNewQueue ON dbo.DataMessages AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
DECLARE @inTabs Table
(ID INT);
/*Part that fetch the IDENTITY() column*/
INSERT INTO @inTabs SELECT DataMessages.ID FROM DataMessages
INNER JOIN inserted INS ON
INS.SenderID = DataMessages.SenderID AND
INS.MssgID = DataMessages.MssgID AND
INS.CreatedAt = DataMessages.CreatedAt;
/*
DataMessages.CreatedAt (DateTime2), DataMessages.MssgID (int) are
ommited from the picture, but those columns AND-ed will guaranteed to
return unique rows because a SenderID cannot have duplicate MssgID
even more on same CreatedAt time
*/
INSERT INTO dbo.DataMessageRecipient (MssgID, RecipID, DestID)
SELECT
inTbl.ID,
DataUser.UserID,
DataUser.DestID
FROM
@inTabs AS inTbl,
DataUser
WHERE
DataUser.UserID IN
(
SELECT Data_UserGroup.UserID
FROM Data_UserGroup
WHERE Data_UserGroup.GroupID IN
(
SELECT Data_UserGroup.GroupID
FROM Data_UserGroup, inserted inr
WHERE Data_UserGroup.UserID = inr.SenderID
)
);
END
我想要实现的目标
我想要实现的是,foreach 插入DataMessages,无论是从单行插入还是多行插入,插入DataMessageRecipient(s) 的条件如下:
-
RecipID和DestID来自DataUser表,其中DataMessages.SenderID共享相同的Data_UserGroup.GroupID(s) -
MssgID来源于插入的DataMessages.ID,RecipID与插入的SenderID相关,基于 No.1 条件 - (SQL 的可选)插入的收件人不能包含其自己的 SenderID 作为 RecipID
问题
INSERT INTO dbo.DataMessages (SenderID)
(10)
INSERT INTO dbo.DataMessages (SenderID)
(-83)
INSERT INTO dbo.DataMessages (SenderID)
(2213)
上述命令/查询的行为和结果符合预期,因为它们中的每一个都是不同的单独查询(满足要求,异常条件编号 3),当多行 INSERT 尝试时(例如,像这样),就会出现问题
INSERT INTO dbo.DataMessages (SenderID)
(10), (83), (2213)
预期的结果是,无论是单行插入还是多行插入,foreach 插入DataMessages,每个插入的都会有“自己的”DataMessageRecipient 条目,RecipID 与每个插入的SenderID 相关,基于@987654356 中的条目@ 其中RecipID 和SenderID 共享相同的GroupID(s)
目前在多行 INSERT 上的结果是,对于每个插入的 DataMessages,“收件人”被合并,因此所有新插入的 DataMessage 将共享相同的收件人
示例
考虑以下数据:
| DataUser | | Data_UserGroup | | DataMessages |
|:------:|:------:|:-:|:------:|:---------:|:-:|:----:|:--------:|
| UserID | DestID | | UserID | GroupID | | ID | SenderID |
| 1 | -1 | | 4 | 10 | | 100 | 4 |
| 2 | -2 | | 5 | 10 | | 101 | 1 |
| 3 | -3 | | 2 | 11 | | 102 | 5 |
| 4 | -4 | | 1 | 12 | | | |
| 5 | -5 | | 1 | 13 | | | |
| 6 | -6 | | 3 | 13 | | | |
| | | | 5 | 13 | | | |
| | | | 6 | 13 | | | |
不管INSERT 的“方式”,它应该是由这个DataMessageRecipient 产生的
| EntryID | MssgID | RecipID | DestID |
|:-------:|:------:|:-------:|:------:|
| | 100 | 4 | -4 |
| | 100 | 5 | -5 |
| | 101 | 1 | -1 |
| | 101 | 3 | -3 |
| | 101 | 5 | -5 |
| | 102 | 5 | -5 |
| | 102 | 4 | -4 |
| | 102 | 1 | -1 |
| | 102 | 3 | -3 |
/*
Note The RecipID is STILL included as the recipients.
This is 'okay' for now, as the logic
outside SQL can filter this out
*/
但是,如果 DataMessage 插入多行 INSERT,则会产生如下结果:
| EntryID | MssgID | RecipID | DestID |
|:-------:|:------:|:-------:|:------:|
| | 101 | 1 | -1 |
| | 101 | 3 | -3 |
| | 101 | 4 | -4 |
| | 101 | 5 | -5 |
| | 102 | 1 | -1 |
| | 102 | 3 | -3 |
| | 102 | 4 | -4 |
| | 102 | 5 | -5 |
| | 103 | 1 | -1 |
| | 103 | 3 | -3 |
| | 103 | 4 | -4 |
| | 103 | 5 | -5 |
问题
我怎样才能达到预期的效果?这有可能在 SQL 逻辑中做这样的事情吗?或者我应该拉出插入的 DataMessages 结果并在后端逻辑中对其进行后处理,我可以在其中为每个循环执行 foreach 插入的 ID?
谢谢
【问题讨论】:
-
FROM @inTabs AS inTbl, DataUser你是故意在这里使用旧样式CROSS JOIN吗? -
@Larnu,我认为不是故意的,因为在正常的
JOIN没有ON的情况下,我的 SQL Studio 不断抛出红色下划线错误并从 Stackoverflows Q&A 中读取一个“简单”的方式来拍打两个 SELECT与CROSS JOIN没有任何关联的结果 -
@Larnu,它适用于单行插入的情况,所以 . . .我不知道这是故意的还是我只是不知道这是否是“旧式”
-
要获取范围内最后插入的标识值,请尝试 scope_identity()。您可以设置一个 var declare @scope_identity int = scope_identity() 并使用该 var 插入到您的其他表中。
-
@JBJ。是的,我知道我可以使用 scope_identity(),但是如果通过单个命令/查询(据我所知)出现多行
INSERT,则 scope_identity() 只会为您提供最后插入的行的标识。这就是为什么我选择手动SELECT“插入的”ID
标签: sql sql-server tsql triggers relationship