Проверьте, возвращает ли SELECT любые строки в хранимой процедуре

Я пишу базовый запрос SELECT, например:

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

Я хотел бы затем выполнить INSERT, используя результат этого SELECT следующим образом:

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**?

Ответы

Ответ 1

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

Вы также можете это сделать, если вы ожидаете, что запрос может часто возвращать строки (особенно много строк), что может обеспечить лучшую возможность короткого замыкания:

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

... так как IF EXISTS вернется сразу же после того, как он попадает в первую строку, которая соответствует.

Я не рекомендую использовать @@ROWCOUNT только потому, что вам придется материализовать (и игнорировать) полный набор результатов каждый раз.

Ответ 2

В MySQL проверить нет. строк, возвращаемых последним выбором запроса

select FOUND_ROWS();

Ответ 3

вы можете использовать @@ROWCOUNT

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

после этого выберите ask for @@ROWCOUNT

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

Таким образом, вы можете вернуть некоторые данные и проверить, были ли у них результаты или нет

Ответ 4

Я видел, что у людей есть проблемы с шаблоном проектирования с этой логикой.

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

Это решение устраняет дубликаты записей и не сообщает о нарушениях ПК.