24

I'm writing a basic SELECT query, something like:

SELECT id, pname, pnumber 
FROM tableName 
WHERE pnumber IS NOT NULL

I'd like to then perform an INSERT by using the result of that SELECT like so:

IF {**the above SELECT query returned 0 rows**}
BEGIN
    INSERT INTO tableName (pname,pnumber) VALUES ('bob', '38499483')
END

My question is, how can I check for the **the above SELECT query returned 0 rows**?

4

5 回答 5

36
IF NOT EXISTS (SELECT ...)
BEGIN
  INSERT ...
END

如果您希望查询可能经常返回行(尤其是很多行),您也可以这样做,这可能会提供更好的短路机会:

IF EXISTS (SELECT ...)
BEGIN
  PRINT 'Do nothing.';
END
ELSE
BEGIN
  INSERT ...
END

...因为IF EXISTS将在它到达匹配的第一行后立即返回。

我不建议@@ROWCOUNT仅使用,因为您每次都必须实现(并忽略)完整的结果集。

于 2013-10-10T17:02:34.313 回答
8

在 MySQL 中,您可以检查从最后一个 SELECT 查询返回的行数,如下所示:

SELECT FOUND_ROWS();
于 2015-02-16T12:15:18.507 回答
2

您可以使用@@ROWCOUNT

SELECT id, pname, pnumber 
FROM tableName 
WHERE pnumber IS NOT NULL

在此选择要求之后@@ROWCOUNT

IF @@ROWCOUNT = 0
BEGIN
  INSERT ...
END

通过这种方式,您可以返回一些数据并检查是否有结果

于 2013-10-10T17:07:09.087 回答
2

代码是:

EXEC(SELECT * FROM Table_Name)
    IF (@@ROWCOUNT>1)    --@@ROWCOUNT is the count number of return's rows
    BEGIN
       // code here
    END
于 2019-11-13T09:17:59.373 回答
0

我见过人们对这种逻辑有设计模式问题。

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 违规。

于 2013-10-10T17:52:54.280 回答