2010-08-08 9 views
28

A)Was ist die effizienteste Möglichkeit zu überprüfen, ob ein Datensatz in Oracle vorhanden ist?

select decode(count(*), 0, 'N', 'Y') rec_exists 
from (select 'X' 
     from dual 
     where exists (select 'X' 
        from sales 
        where sales_type = 'Accessories')); 

B)

select decode(count(*), 0, 'N', 'Y') rec_exists 
from (select 'X' 
     from sales 
     where sales_type = 'Accessories'); 

C) Etwas anderes (bitte angeben)

EDIT: Es war schwer, die "richtige" Antwort zu holen, als der beste Ansatz abhängt, was Sie tun möchten, nachdem Sie überprüft haben, ob der Wert existiert, wie von APC angegeben. Am Ende habe ich die Antwort von RedFilter ausgewählt, da ich diesen Check ursprünglich als eine Funktion für sich betrachtet hatte.

+0

(Sehr alte Frage, ich weiß ...) Manchmal muss ich eine einfache Überprüfung nach "ist das eine gültige ID-Nummer" (dh existiert es bereits) von einem serverseitigen Programm (PHP), also mache ich eine einfache SQL-Abfrage: 'SELECT null FROM table_name WHERE id =: id' (mit vorbereiteten Anweisungen,': id'). Wenn Zeilen zurückgegeben wurden, lautet die Antwort ja. Ansonsten, nein. Die tatsächlich zurückgegebenen Daten sind irrelevant. – user128216

Antwort

60
select case 
      when exists (select 1 
         from sales 
         where sales_type = 'Accessories') 
      then 'Y' 
      else 'N' 
     end as rec_exists 
from dual; 
+1

Sieht ziemlich gut aus. Vielen Dank! – Zesty

+5

Sie vermissen ein 'FROM dual'. –

+0

Danke, das habe ich behoben. – RedFilter

0
select decode(count(*), 0, 'N', 'Y') rec_exists 
     from sales 
     where sales_type = 'Accessories'; 
-3
SELECT 'Y' REC_EXISTS    
FROM SALES      
WHERE SALES_TYPE = 'Accessories' 

Das Ergebnis wird entweder 'Y' oder NULL sein. Einfach Test 'Y'

+2

Das Ergebnis ist 'Y', wenn ein Datensatz existiert. Wenn mehrere Datensätze vorhanden sind, handelt es sich um eine TOO_MANY_ROWS-Ausnahme. Wenn keine Datensätze vorhanden sind, handelt es sich um eine NO_DATA_FOUND-Ausnahme. – APC

+0

@APC: Nicht, es sei denn, Sie SELECT in eine einzelne Variable. Die geschriebene Abfrage ist reines SQL und löst keine Ausnahmen aus. – ObiWanKenobi

+2

@ObiWanKenobi - Wie testen Sie einen Wert, es sei denn, Sie wählen ihn in eine Variable aus? – APC

13

Was ist die zugrunde liegende Logik, die Sie implementieren möchten? Wenn Sie zum Beispiel die Existenz eines Datensatzes testen möchten, um festzustellen, ob er eingefügt oder aktualisiert werden soll, dann wäre es besser, stattdessen MERGE zu verwenden.

Wenn Sie den Datensatz erwarten die meiste Zeit zu existieren, ist dies wahrscheinlich die effizienteste Art und Weise, Dinge zu tun (obwohl die CASE WHEN EXISTS Lösung ist wahrscheinlich genauso effizient sein):

begin 
    select null into dummy 
    from sales 
    where sales_type = 'Accessories' 
    and rownum = 1; 

    -- do things here when record exists 
    ....   

exception 
    when no_data_found then 
     -- do things here when record doesn't exists 
     ..... 
end; 

Sie brauchen nur die ROWNUM-Zeile, wenn SALES_TYPE nicht eindeutig ist. Es macht keinen Sinn, eine Zählung durchzuführen, wenn Sie nur wissen wollen, ob mindestens ein Datensatz existiert.

+1

+1 Schöne Antwort. Ich benutze diesen Check häufig unter verschiedenen Umständen ... deshalb habe ich mich gefragt, wie ich das am besten machen könnte. Manchmal möchte ich nur eine Flagge an das Frontend zurückgeben. In anderen Fällen tue ich etwas anderes, z. B. gebe einen Wert zurück, wenn er existiert, und falls nicht, gebe den nächsten Wert einer Sequenz zurück. Ich nehme an, Sie haben recht - der beste Weg könnte von der Situation abhängen. – Zesty

1

Hier können Sie nur y, n überprüfen, wenn wir auch einen Namen auswählen müssen, ob dieser Name existiert oder nicht.

select name , decode(count(name),0, 'N', 'Y') 
    from table 
group by name; 

hier, wenn es Y nur dann wird es Ausgabe zurückgeben sonst wird es null immer geben. Whts ths Weg, um die Datensätze nicht mit N bestehenden wie in der Ausgabe werden wir Namen, N. bekommen Wenn Name vorhanden ist, wird nicht in der Tabelle

7
select count(1) into existence 
    from sales where sales_type = 'Accessories' and rownum=1; 

Oracle Plan sagt, dass es 1 kostet, wenn seles_type Spalte indiziert ist.

+7

Dies ist die Methode, die ich normalerweise verwende, aber count (1) sollte eigentlich zählen (\ *) - es gibt nichts besonderes über count (1) und count (\ *) ist die Standardsyntax. –

+1

count (1) bedeutet, dass wir einfach nichts anderes zählen. Es ist einfacher zu lesen, denke ich. – tyger

+1

Das ist was zählt (\ *) bedeutet.In diesem Zusammenhang bedeutet "\ *" nicht "alle Spalten" in dem Sinne, dass es in "select \ * from" –

0
select NVL ((select 'Y' from dual where exists 
    (select 1 from sales where sales_type = 'Accessories')),'N') as rec_exists 
from dual 

1.Dual Tisch kehrt 'Y', wenn Datensatz in sales_type Tabelle vorhanden 2.Dual Tabelle null zurück, wenn kein Datensatz in sales_type Tabelle vorhanden ist und NVL wird, dass

+0

Bitte fügen Sie der Antwort eine Erklärung hinzu, um Ihren Code zu unterstützen. – Rachcha

0

auf 'N' konvertieren Der effizienteste und sicherste Weg, um festzustellen, ob eine Zeile existiert, ist die Verwendung eines FOR-LOOP ... Sie werden nicht einmal eine schwierige Zeit haben, wenn Sie eine Zeile einfügen oder etwas tun möchten, das nicht auf der Zeile steht Aber das wird Ihnen sicherlich helfen, wenn Sie feststellen müssen, ob eine Zeile existiert. Siehe Beispielcode unten für die Ein- und Ausgänge ...

Wenn Sie nur wissen möchten, dass 1 Datensatz in Ihrer potenziellen Mehrfachrückgabe vorhanden ist, können Sie Ihre Schleife beenden, nachdem sie sie zum ersten Mal erreicht hat.

Die Schleife wird überhaupt nicht aufgerufen, wenn kein Datensatz existiert. Sie werden keine Beschwerden von Oracle erhalten oder solche, wenn die Zeile nicht existiert, aber Sie müssen herausfinden, ob es trotzdem funktioniert.Sein, was verwende ich 90% der Zeit (natürlich auf meine Bedürfnisse abhängig) ...

Beispiel:

DECLARE 

v_exist varchar2(20); 

BEGIN 
    FOR rec IN 
    (SELECT LOT, COMPONENT 
    FROM TABLE 
    WHERE REF_DES = (SELECT REF_DES FROM TABLE2 WHERE ORDER = '1234') 
    AND ORDER = '1234') 
    LOOP 

     v_exist := "IT_EXISTS" 

    INSERT INTO EAT_SOME_SOUP_TABLE (LOT, COMPONENT) 
    VALUES (rec.LOT, rec.COMPONENT);** 

    --Since I don't want to do this for more than one iteration (just in case there may have been more than one record returned, I will EXIT; 

    EXIT; 
    END LOOP; 



IF v_exist IS NULL 

    THEN 

      --do this 

END IF; 

END; 

--Dieser außerhalb der Schleife ist hier die IF-CHECK nur oben wird run unabhängig, aber dann wissen Sie, ob Ihre Variable null oder nicht richtig ist!?. Wenn KEINE Datensätze zurückgegeben wurden, wird die Schleife übersprungen und Sie gehen einfach zu dem Code, den Sie als nächstes haben würden ... Wenn (in unserem Fall oben) 4 Datensätze zurückgegeben würden, würde ich nach der ersten Iteration aufgrund meines EXITs beenden ; ... Wenn das nicht da wäre, würden die 4 Datensätze durchgehen und alle einfügen. Oder zumindest versuchen Sie es auch. Es

By the way, ich sage nicht, dies die einzige Möglichkeit ist, dass Sie dies in Erwägung ziehen sollte ... Sie können

SELECT COUNT(*) INTO v_counter WHERE ******* etc... 

überprüfen Sie es dann wie

if v_counter > 0 
     THEN 
     --code goes here 
    END IF; 

Es gibt mehr Möglichkeiten ... Bestimmen Sie es einfach, wenn Ihre Notwendigkeit entsteht. Achten Sie auf Leistung und Sicherheit.

-1

Erhalten Sie einfach eine Anzahl der Datensätze, die Sie suchen. Wenn count> 0, dann existieren records (s).

 
    DECLARE 
    rec_count NUMBER := 0; 

    BEGIN 

    select count(*) 
    into rec_count 
    from EMPLOYEETABLE 
    WHERE employee_id = inEMPLOYEE_ID 
    AND department_nbr = inDEPARTMENT_NBR; 


    if rec_count > 0 then 
     {UPDATE EMPLOYEETABLE} 
    else 
     {INSERT INTO EMPLOYEETABLE} 
    end if; 

    END; 
Verwandte Themen