我正在编写一个基本的SELECT
查询,如下所示:
SELECT id, pname, pnumber
FROM tableName
WHERE pnumber IS NOT NULL
然后,我想使用该SELECT
的结果执行INSERT
,如下所示:
IF {**the above SELECT query returned 0 rows**}
BEGIN
INSERT INTO tableName (pname,pnumber) VALUES ('bob', '38499483')
END
我的问题是,如何检查**the above SELECT query returned 0 rows**
?
IF NOT EXISTS (SELECT ...)
BEGIN
INSERT ...
END
如果您预计查询可能经常返回行(尤其是大量行(,也可以这样做,这可能会提供更好的短路机会:
IF EXISTS (SELECT ...)
BEGIN
PRINT 'Do nothing.';
END
ELSE
BEGIN
INSERT ...
END
。因为IF EXISTS
会在击中匹配的第一行后立即返回。
我不建议仅使用 @@ROWCOUNT
,因为您每次都必须实现(并忽略(完整的结果集。
在MySQL中,你可以检查从上一个SELECT查询返回的行数,如下所示:
SELECT FOUND_ROWS();
您可以使用@@ROWCOUNT
SELECT id, pname, pnumber
FROM tableName
WHERE pnumber IS NOT NULL
在此之后选择"询问@@ROWCOUNT
IF @@ROWCOUNT = 0
BEGIN
INSERT ...
END
通过这种方式,您可以返回一些数据并检查是否有结果
代码是:
EXEC(SELECT * FROM Table_Name)
IF (@@ROWCOUNT>1) --@@ROWCOUNT is the count number of return's rows
BEGIN
// code here
END
我见过人们对这种逻辑有设计模式问题。
1 - 测试记录是否存在。
2 - 如果不存在,请插入记录。
特别是当并发性发挥作用时。 根据隔离级别,可能会有重复的数据或密钥冲突。
为什么不首先在 pname 和 pnumber 上放置一个主键。 我假设您正在谈论人员表。
我的例子。
--
-- Setup sample table w/data
--
-- Sample table
create table #person
(
person_id int identity (1, 1),
person_name varchar(64) not null,
person_no varchar(16) not null
);
go
-- primary key
alter table #person
add primary key (person_no, person_name)
go
-- first insert works
insert into #person (person_name, person_no) values ('bilbo', 123)
go
解决方案的关键是捕获主键冲突。 忽略此错误可能是好是坏,具体取决于您的业务逻辑。
我决定忽略这个问题。
--
-- Ignore primary key violations
--
-- Try these steps
BEGIN TRY
-- Second insert fails
insert into #person (person_name, person_no) values ('bilbo', 123)
END TRY
-- Error Handler
BEGIN CATCH
-- Ignore PK error
IF ERROR_NUMBER() <> 2627
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
此解决方案消除了重复条目,并且不会报告 PK 违规。