我有一个父和子表,我需要插入数据。对于创建的每个父任务,需要添加子任务,引用父ID。
XML结构:
<request>
<task>
<user>Q500</user>
<tool>31</tool>
<role>
<roleID>w1234</roleID>
<action>2</action>
</role>
</task>
<task>
<user>Q500</user>
<tool>31</tool>
<role>
<roleID>w123456</roleID>
<action>1</action>
</role>
</task>
</request>
插入父级(任务):
-- Add tasks
INSERT INTO Task
( RequestID ,
ToolID ,
QID
)
SELECT @requestID,
ParamValues.x1.value('tool[1]', 'INT'),
ParamValues.x1.value('user[1]', 'VARCHAR(10)')
FROM @tasks.nodes('/request/task') AS ParamValues(x1);
插入儿童(角色):
INSERT INTO TaskRole
( TaskID,
RoleID,
ActionID )
SELECT t.TaskID,
ParamValues.x1.value('roleID[1]', 'varchar(10)'),
ParamValues.x1.value('action[1]', 'INT')
FROM Task AS t
JOIN @tasks.nodes('/request/task/role') AS ParamValues(x1)
ON t.RequestID = @requestID
AND t.ToolID = ParamValues.x1.value('../tool[1]', 'INT')
AND t.QID = ParamValues.x1.value('../user[1]', 'VARCHAR(10)')
上述代码的问题是user
和tool
在多个任务中可能相同,所以当需要加入时,我会收到大量重复的条目。
在这种情况下,子查询正在查找具有ToolID=31
和User=Q500
的父任务。由于有两个,它插入两个不正确的记录,每个父母应该只有一个孩子。
我还有什么办法可以实现这个目标,因为我没有什么独特的东西可以加入?
更新1(任务表结构):
CREATE TABLE [Task](
[TaskID] [INT] IDENTITY(1,1) NOT NULL,
[RequestID] [INT] NOT NULL,
[ToolID] [INT] NOT NULL,
[QID] [VARCHAR](10) NOT NULL,
[StatusID] [INT] NOT NULL CONSTRAINT [DF_Task_StatusID] DEFAULT ((1)),
[TaskOwner] [VARCHAR](10) NULL,
CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED
(
[TaskID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [TaskRole](
[TaskID] [INT] NOT NULL,
[RoleID] [VARCHAR](10) NOT NULL,
[ActionID] [INT] NOT NULL,
CONSTRAINT [PK_TaskRoles] PRIMARY KEY CLUSTERED
(
[TaskID] ASC,
[RoleID] ASC,
[ActionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
更新2 - 示例代码:
这是我想要做的一个例子。在第一次传递时插入父(任务),以便为它们创建AI/PK
。然后,我需要将子记录(角色)插入到另一个表中,引用它所属的任务。
DECLARE @parent TABLE (requestID INT IDENTITY,qid varchar(10), tool int)
DECLARE @child TABLE (taskID INT IDENTITY, requestID INT, roleID VARCHAR(20), actionID int)
INSERT INTO @parent( qid, tool ) VALUES ( 'Q500', 31) -- Task 1
INSERT INTO @parent( qid, tool ) VALUES ( 'Q500', 31) -- Task 2
INSERT INTO @child( requestID, roleID, actionID ) VALUES (1, 'w1234', 2) -- Role for Task 1
INSERT INTO @child( requestID, roleID, actionID ) VALUES (1, 'w123456', 1) -- Role for Task 2
SELECT *
FROM @parent AS p
JOIN @child AS c
ON p.requestID = c.requestID
答案 0 :(得分:1)
答案 1 :(得分:0)
所以问题是你需要将来自任务的身份TaskID
与正确的角色相关联,但是你的源数据中没有任何与回归相关的独特信息。插入Task的行。您可以使用游标插入Task并输出每行的标识列,然后插入TaskRole,但这样效率非常低。
幸运的是,MERGE
的一个技巧是你不仅可以OUTPUT
插入列(TaskID),还可以使用源列 - 甚至是未使用过的列,例如RoleID和ActionID。因此,您可以使用MERGE
作为内部查询的一部分插入Task,并使用输出插入TaskRole。
请注意ON 1 = 0
。这基本上迫使MERGE
表现得像INSERT
。
INSERT INTO TaskRole (TaskID, RoleID, ActionID)
SELECT TaskID, RoleID, ActionID
FROM (
MERGE INTO Task
USING (
SELECT pv.item.value('../user[1]', 'VARCHAR(10)') AS QID
, pv.item.value('../tool[1]', 'INT') AS ToolID
, pv.item.value('roleID[1]', 'varchar(10)') RoleID
, pv.item.value('action[1]', 'INT') ActionID
FROM @tasks.nodes('/request/task/role') pv(item)
) AS src
ON 1 = 0
WHEN NOT MATCHED THEN INSERT (RequestID, ToolID, QID) VALUES (@RequestID, ToolID, QID)
OUTPUT Inserted.TaskID, src.RoleID, src.ActionID
) src;