SQL:编写忽略现有项的大容量插入脚本
我从一个使用sql数据库的现有程序开始,尝试对其进行修改,使其使用大容量插入,而不是逐个插入,并防止重复条目 以下是我的函数添加一个用户所得到的信息,只要该用户不存在,该功能应该可以工作:SQL:编写忽略现有项的大容量插入脚本,sql,stored-procedures,bulkinsert,Sql,Stored Procedures,Bulkinsert,我从一个使用sql数据库的现有程序开始,尝试对其进行修改,使其使用大容量插入,而不是逐个插入,并防止重复条目 以下是我的函数添加一个用户所得到的信息,只要该用户不存在,该功能应该可以工作: use [DebugDatabase] go set ansi_nulls on go set quoted_identifier on go create procedure [dbo].[AddUser] @Id bigint, @Login nvarchar(100), @ConsoleN
use [DebugDatabase]
go
set ansi_nulls on
go
set quoted_identifier on
go
create procedure [dbo].[AddUser]
@Id bigint, @Login nvarchar(100), @ConsoleName nvarchar(100), @Ip nvarchar(50)
as
begin
set nocount on;
declare @FoundId bigint = (select Id from [User] where Id = @Id)
if @FoundId is null
begin
insert into [User] (Id, Login, ConsoleName, Ip) values (@Id, @Login, @ConsoleName, @Ip)
end
else
begin
update [User]
set [Id] = @Id,
[Login] = @Login,
[ConsoleName] = @ConsoleName,
[Ip] = @Ip
where Id = @Id
end
select top 1 * from [User] where Id = @Id;
end
go
现在我想为批量插入编写一个函数,它调用上述函数来检查每个条目。按照我的展示方式,这需要一个自定义表类型:
use [DebugDatabase]
go
create type [dbo].[UserTableType] as table
(
[Id] [bigint] not null,
[Login] [nvarchar](100) not null default 'Unknown',
[ConsoleName] [nvarchar](100) not null default 'Unknown',
[Ip] [nvarchar](50) not null default '0.0.0.0'
)
go
添加多个条目的函数这是我遇到的问题:
use [DebugDatabase]
go
set ansi_nulls on
go
set quoted_identifier on
go
create procedure [AddMultipleUsers]
@users UserTableType readonly
as
declare
@Id bigint,
@Login nvarchar(100),
@ConsoleName nvarchar(100),
@Ip nvarchar(50)
begin
insert into @Id select Id from @users
insert into @Login select Login from @users
insert into @ConsoleName select ConsoleName from @users
insert into @Ip select Ip from @users
exec AddUser @Id, @Login, @ConsoleName, @Ip
end
go
我必须声明表变量@Id。我不确定如何从表类型中提取单个值,以便将它们传递给AddUser函数。不过,我真正喜欢的是一种在一个函数调用中完成所有操作的方法,但我还没有遇到过类似的方法。这种类型的操作可以使用单个查询完成,而无需使用存储过程。顺便说一句,请使用正确的术语:AddUser是一个存储过程,而不是函数。请看一下命令
create procedure [AddMultipleUsers]
@users UserTableType readonly
as
declare
@Id bigint,
@Login nvarchar(100),
@ConsoleName nvarchar(100),
@Ip nvarchar(50)
-- A opcion ...
-- Declare the cursor for the list of users to be processed.
DECLARE userT CURSOR FOR SELECT * FROM UserTableType ;
-- Open the cursor.
OPEN userT;
-- Loop through the users.
FETCH NEXT
FROM userT
INTO @Id, @Login, @ConsoleName, @Ip;
WHILE @@FETCH_STATUS = 0
BEGIN;
exec AddUser @Id, @Login, @ConsoleName, @Ip
FETCH NEXT FROM userT INTO @Id, @Login, @ConsoleName, @Ip;
END;
-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;
这种类型的操作可以使用单个查询完成,而无需使用存储过程。顺便说一句,请使用正确的术语:AddUser是一个存储过程,而不是函数。请看一下命令
这种类型的操作可以使用单个查询完成,而无需使用存储过程。顺便说一句,请使用正确的术语:AddUser是一个存储过程,而不是函数。请看一下命令
这种类型的操作可以使用单个查询完成,而无需使用存储过程。顺便说一句,请使用正确的术语:AddUser是一个存储过程,而不是函数。请看一下命令
您对“@Id”的插入无效,因为“@Id”是bigint而不是表。您应该像这样设置@Id参数:“set@Id=Select top 1id from@users”您对“@Id”的插入将不起作用,因为“@Id”是一个bigint而不是一个表。您应该像这样设置@Id参数:“set@Id=Select top 1id from@users”您对“@Id”的插入将不起作用,因为“@Id”是一个bigint而不是一个表。您应该像这样设置@Id参数:“set@Id=Select top 1id from@users”您对“@Id”的插入将不起作用,因为“@Id”是一个bigint而不是一个表。您应该这样设置@Id参数:'set@Id=selecttop1id from@users'Thank,到目前为止似乎效果不错。因为长期目标是使用实体框架从c程序调用它,我相信它必须存储为一个过程。只需放入[AddMultipleUsers]的主体中,去掉您的DECLARE语句,这正是我所做的。谢谢你的帮助,cha。谢谢,到目前为止这似乎效果不错。因为长期目标是使用实体框架从c程序调用它,我相信它必须存储为一个过程。只需放入[AddMultipleUsers]的主体中,去掉您的DECLARE语句,这正是我所做的。谢谢你的帮助,cha。谢谢,到目前为止这似乎效果不错。因为长期目标是使用实体框架从c程序调用它,我相信它必须存储为一个过程。只需放入[AddMultipleUsers]的主体中,去掉您的DECLARE语句,这正是我所做的。谢谢你的帮助,cha。谢谢,到目前为止这似乎效果不错。因为长期目标是使用实体框架从c程序调用它,我相信它必须存储为一个过程。只需放入[AddMultipleUsers]的主体中,去掉您的DECLARE语句,这正是我所做的。谢谢你的帮助,查。
MERGE [User] AS target
USING (SELECT [Id], [Login], [ConsoleName], [Ip] FROM @users) AS source
(Id, Login, ConsoleName, Ip)
ON (target.Id = source.Id)
WHEN MATCHED THEN
UPDATE SET [Login] = source.Login,
[ConsoleName] = source.ConsoleName,
[Ip] = source.Ip
WHEN NOT MATCHED THEN
INSERT (Id, Login, ConsoleName, Ip)
VALUES (source.Id, source.Login, source.ConsoleName, source.Ip);