SQL Server存储过程在插入之前检查记录是否存在
在将记录插入表之前,我正在检查它是否存在(这种方法似乎适用于我已经在使用的其他存储过程),但是对于这个特定的存储过程,即使表是空的,它也不会插入任何内容,为什么不呢SQL Server存储过程在插入之前检查记录是否存在,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,在将记录插入表之前,我正在检查它是否存在(这种方法似乎适用于我已经在使用的其他存储过程),但是对于这个特定的存储过程,即使表是空的,它也不会插入任何内容,为什么不呢 CREATE PROCEDURE spInsertMovieHasTrailer @movieID int, @name varchar(50) AS BEGIN SELECT @name = name, @movieID = movieID FROM MovieHasTrailer WHER
CREATE PROCEDURE spInsertMovieHasTrailer
@movieID int,
@name varchar(50)
AS
BEGIN
SELECT @name = name, @movieID = movieID
FROM MovieHasTrailer
WHERE name = @name and movieID = @movieID
IF @name IS NULL and @movieID IS NULL
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
@movieID,
@name
)
END
END
这样执行:
execute spInsertMovieHasTrailer 1, 'Test'
您的select into变量可能返回多个值,并且您会得到错误,如果不存在,最好使用
:
IF NOT EXISTS
(
SELECT name, movieID
FROM MovieHasTrailer
WHERE name = @name and movieID = @movieID
)
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
@movieID,
@name
)
END
您的select into变量可能返回多个值,并且您会得到错误,如果不存在,最好使用:
IF NOT EXISTS
(
SELECT name, movieID
FROM MovieHasTrailer
WHERE name = @name and movieID = @movieID
)
BEGIN
INSERT INTO MovieHasTrailer
(
movieID,
name
)
Values (
@movieID,
@name
)
END
我会将其直接构建到insert
中,而不使用if
逻辑<代码>如果
引入竞争条件:
INSERT INTO MovieHasTrailer
SELECT movieID, name
FROM (SELECT @movieID as movieID, @name as name) t
WHERE NOT EXISTS (SELECT 1
FROM MovieHasTrailer mht
WHERE mht.MovieId = t.MovieID AND mht.name = t.name
);
注意,这假设您需要id和名称来匹配电影。我认为id
就足够了
另外,我真正要做的是在moviehastraile(MovieId)
或moviehastraile(MovieId,Name)
上有一个唯一的索引。如果存在插入错误,则使用try
/catch
块。我将直接将其构建到插入
中,而不使用if
逻辑<代码>如果
引入竞争条件:
INSERT INTO MovieHasTrailer
SELECT movieID, name
FROM (SELECT @movieID as movieID, @name as name) t
WHERE NOT EXISTS (SELECT 1
FROM MovieHasTrailer mht
WHERE mht.MovieId = t.MovieID AND mht.name = t.name
);
注意,这假设您需要id和名称来匹配电影。我认为id
就足够了
另外,我真正要做的是在
moviehastraile(MovieId)
或moviehastraile(MovieId,Name)
上有一个唯一的索引。如果存在插入错误,则使用try
/catch
块。不执行插入的原因是,如果查询未返回任何记录,则以下代码不会更改@name和@movieID的值
SELECT @name = name, @movieID = movieID
FROM MovieHasTrailer
WHERE name = @name and movieID = @movieID
传递到存储过程中的@name和@movieID的任何值都保持不变。我假设您没有传入null值,因此IF块永远不会执行。您没有执行插入的原因是,如果查询没有返回任何记录,以下代码将不会更改@name和@movieID的值
SELECT @name = name, @movieID = movieID
FROM MovieHasTrailer
WHERE name = @name and movieID = @movieID
传递到存储过程中的@name和@movieID的任何值都保持不变。我假设您没有传递null值,因此IF块永远不会执行。您也可以尝试这种方法,您可以实现您的目标,也可以节省您的时间
INSERT INTO MovieHasTrailer
SELECT @movieID as movieID, @name as name
except
select MovieId, name
FROM MovieHasTrailer mht
where MovieId = @MoveID
你可以尝试这种方式,你也可以实现你的目标,它也节省你的时间
INSERT INTO MovieHasTrailer
SELECT @movieID as movieID, @name as name
except
select MovieId, name
FROM MovieHasTrailer mht
where MovieId = @MoveID
我会通过standart
MERGE
语句来实现这一点:
Create table t(id int, name nvarchar(max))
Declare @id int = 1, @name nvarchar(max) = 'Mission imposible'
Merge t using (select @id, @name) as s(id, name)
on t.id = s.id
when not matched then
insert(id, name) values(s.id, s.name);
您还可以在匹配时添加,然后更新,在不匹配源时删除
小提琴:我会用标准的MERGE
语句:
Create table t(id int, name nvarchar(max))
Declare @id int = 1, @name nvarchar(max) = 'Mission imposible'
Merge t using (select @id, @name) as s(id, name)
on t.id = s.id
when not matched then
insert(id, name) values(s.id, s.name);
您还可以在匹配时添加,然后更新,在不匹配源时删除
Fiddle:尝试切换到简单的@@ROWCOUNT检查()尝试切换到简单的@@ROWCOUNT检查()