web-dev-qa-db-fra.com

Vérifiez si SELECT renvoie des lignes dans la procédure stockée

J'écris une requête de base SELECT, quelque chose comme:

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

Je voudrais ensuite effectuer un INSERT en utilisant le résultat de ce SELECT comme ceci:

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

Ma question est, comment puis-je vérifier le **the above SELECT query returned 0 rows**?

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

Vous pouvez également le faire, si vous vous attendez à ce que la requête retourne souvent des lignes (en particulier beaucoup de lignes), ce qui peut offrir une meilleure opportunité de court-circuiter:

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

...puisque IF EXISTS reviendra immédiatement après avoir atteint la toute première ligne correspondante.

Je ne recommande pas d'utiliser @@ROWCOUNT uniquement parce que vous devrez à chaque fois matérialiser (et ignorer) l'ensemble des résultats.

31
Aaron Bertrand

Dans MySQL pour vérifier non. des lignes retournées par la dernière requête de sélection

select FOUND_ROWS();
4
Sunil Kumar

vous pouvez utiliser @@ROWCOUNT

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

après cette sélection, demandez @@ROWCOUNT

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

De cette façon, vous pouvez renvoyer certaines données et vérifier si cela a donné des résultats ou non

2
Federico

J'ai vu des gens avoir des problèmes de conception avec cette logique.

1 - Tester l'existence de l'enregistrement.
2 - S'il n'existe pas, insérez l'enregistrement.

Surtout si la concurrence entre en jeu. Selon le niveau d'isolement, vous pouvez avoir des données en double ou des violations de clé.

Pourquoi ne pas placer une clé primaire sur pname et pnumber en premier lieu. Je suppose que vous parlez d'une table de personnes.

Mon exemple.

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

La clé de la solution consiste à intercepter la violation de clé primaire. Ignorer cette erreur peut être bon ou mauvais selon votre logique métier.

Je décide d'ignorer le problème.

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

Cette solution élimine les entrées en double et ne signale pas les violations de PK.

0
CRAFTY DBA