2013-10-10 15 views
12

Sto scrivendo una base SELECT interrogazione, qualcosa di simile:Controllare se SELECT restituisce tutte le righe in stored procedure

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

mi piacerebbe quindi eseguire un INSERT utilizzando il risultato di tale SELECT in questo modo:

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

la mia domanda è, come posso verificare la **the above SELECT query returned 0 rows**?

+0

Qual è lo scopo di questo controllo? Se stai verificando l'unicità, un indice univoco sulle colonne è più semplice. – podiluska

risposta

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

si potrebbe anche farlo, se ci si aspetta che la query potrebbe restituire le righe spesso (soprattutto un sacco di righe), che può offrire una migliore opportunità di corto circuito:

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

.. .since IF EXISTS restituirà immediatamente dopo che colpisce la prima riga che corrisponde.

Non è consigliabile utilizzare @@ROWCOUNT solo perché si dovrà materializzare (e ignorare) il set di risultati completo ogni volta.

+0

Ovviamente, avrei dovuto saperlo ... grazie. – muttley91

+0

Mi piace.Spesso le soluzioni a bassa tecnologia sono buone perché non sono specifiche dell'ambiente. Il codice SQL viene spesso portato da SQL Server a MySQL a Oracle, ecc ... –

1

è possibile utilizzare @@ROWCOUNT

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

dopo questo seleziona Chiedi @@ROWCOUNT

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

In questo modo è possibile restituire alcuni dati e verificare se questo ha avuto i risultati o no

0

ho le persone viste hanno problemi di progettazione con questa logica.

1 - Verificare l'esistenza del record.
2 - Se non esiste, inserire il record.

Specialmente se entra in gioco la concorrenza. A seconda del livello di isolamento, potresti avere dati duplicati o violazioni delle chiavi.

Perché non inserire una chiave primaria su pname e pnumber in primo luogo. Suppongo che tu stia parlando di un tavolo per persone.

Il mio esempio.

-- 
-- 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 chiave della soluzione è intercettare la violazione della chiave primaria. Ignorare questo errore potrebbe essere un aspetto positivo o negativo a seconda della logica aziendale.

Ho deciso di ignorare il problema.

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

Questa soluzione elimina le voci duplicate e non segnala violazioni PK.

+0

Stavo cercando di eseguire SOLO un INSERT se non esisteva perché stavo correndo in un problema di postback in ASP.NET. Quindi il record esistente significava che non era necessario inserirlo perché era già stato registrato. Detto questo, prenderò in considerazione la tua risposta nelle prossime modifiche al design. Grazie. – muttley91

+0

Ho un prodotto Microsoft su uno dei miei server che sta facendo la stessa logica. Se esiste, quindi restituire la chiave in caso contrario, inserire con il blocco di aggiornamento. Ricevo costantemente notifiche di deadlock nel mio sistema SQL Sentry Monitoring. La soluzione che ho proposto era la precedente, ma non l'hanno ancora implementata! –

5

In MySQL per controllare no. di righe restituite dall'ultima query di selezione

select FOUND_ROWS(); 
Problemi correlati