检查 SELECT 是否返回存储过程中的任何行



我正在编写一个基本的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 违规。

最新更新