Sql 对每行执行多个插入
简单地说,我的问题是如何在没有游标(伪代码)的情况下在t-sql 2012中执行以下操作: 长问题: 假设我有以下3个表,模拟对象可以是文件或目录的事实Sql 对每行执行多个插入,sql,tsql,insert,Sql,Tsql,Insert,简单地说,我的问题是如何在没有游标(伪代码)的情况下在t-sql 2012中执行以下操作: 长问题: 假设我有以下3个表,模拟对象可以是文件或目录的事实 obj(id int, creation_date datetime) -- all objects have a creation date. file(id int, id_obj int, path nvarchar(max)) -- id_obj is a foreign key to obj dir(id int, id_obj
obj(id int, creation_date datetime) -- all objects have a creation date.
file(id int, id_obj int, path nvarchar(max)) -- id_obj is a foreign key to obj
dir(id int, id_obj int, path nvarchar(max), shared bit) -- id_obj is a foreign key to obj
我需要编写一个存储过程,它接受一个“逻辑对象”列表(可以表示文件或目录),并且必须将它们添加到数据库中,即它必须为每个逻辑对象创建1)obj中的一行,2)file或dir中的一行(取决于逻辑对象是表示文件还是目录)
为了编写这个存储过程,我创建了一个表示逻辑对象的表参数。这必须能够表示文件和目录,因此它必须包含文件和目录(逻辑)字段的合并,如下所示:
create type logicalObj as table(
dirPath nvarchar(max) null,
dirShared bit null,
filePath nvarchar(max) null
)
create procedure foo
-- this way the user can pass a list of logical objects to the stored proc
@lo logicalObj readonly .
as
begin
...
end
我的存储过程是使用表值参数定义的,如下所示:
create type logicalObj as table(
dirPath nvarchar(max) null,
dirShared bit null,
filePath nvarchar(max) null
)
create procedure foo
-- this way the user can pass a list of logical objects to the stored proc
@lo logicalObj readonly .
as
begin
...
end
现在在过程主体中,我想我需要做一些类似(伪代码)的事情:
我的问题是:没有游标怎么做?如果需要,可以使用t-sql 2012独有的功能(如序列)。为什么不将其作为三个插入来执行呢 大概是这样的:
INSERT into obj(creation_date)
SELECT curdate() FROM @lo WHERE (lo.dirPath is not null) OR (lo.dirPath is null AND lo.filePath is not null)
insert into dir(id_obj, path, shared)
SELECT @@identity, lo.dirPath, 1 FROM @lo WHERE lo.dirPath is not null
insert into file(id_obj, path)
SELECT @@identity, lo.dirPath, 1 FROM @lo lo WHERE lo.dirPath is null AND lo.filePath is not null
可以使用从第一次基于集合的插入中捕获具有标识值的多行。然后可以使用子句将这些捕获的输出值与原始@lo
变量中的行相关联
它将类似于:
declare @IDs table (ID int not null)
insert into obj(creation_date)
output inserted.id into @IDs
select curdate() from @lo --Just makes sure there's one row per row in @lo
;with NumberedIDs as (
select ID,ROW_NUMBER() OVER (ORDER BY ID) as rn from @IDs
), NumberedObjects as (
select *,ROW_NUMBER() OVER (ORDER BY dirPath,filePath) as rn from @lo
)
insert into dir (id_obj, path, shared)
select nid.ID,no.dirPath,no.dirShared
from NumberedObjects no
inner join
NumberedIDs nid
on
no.rn = nid.rn
where
no.dirPath is not null
;with NumberedIDs as (
select ID,ROW_NUMBER() OVER (ORDER BY ID) as rn from @IDs
), NumberedObjects as (
select *,ROW_NUMBER() OVER (ORDER BY dirPath,filePath) as rn from @lo
)
insert into file (id_obj, path)
select nid.ID,no.filePath
from NumberedObjects no
inner join
NumberedIDs nid
on
no.rn = nid.rn
where
no.filePath is not null
在底部两个insert中的
numberobjects
中完全查询@lo
很重要,而且不要过早筛选,以便行号保持匹配。我认为这不起作用,因为第一个“insert into obj”插入一组行,每个行都有新的@标识。然后,当您选择@@identity时,您只使用最后创建的标识。