Frage

Ich habe ein paar Szenarien:

  1. Sie benötigen den Wert einer Spalte aus drei verschiedenen Tabellen in einer vorgegebenen Reihenfolge und nur 1 Tabelle lesen wird die Daten haben

  2. Daten aus table1 Lesen, wenn Datensätze nach Kriterien vorhanden sind gegeben andere Daten aus Tabelle 2 zu lesen für bestimmte Kriterien

In Oracle Stored Procedures

Die Art, wie diese jetzt behandelt werden, ist zuerst die Zählung für eine bestimmte Abfrage in eine Variable zu erhalten, und wenn die Zählung> 0, dann führen wir die gleiche Abfrage die aktuellen Daten wie in zu lesen:

select count(*) from table1 into v_count
if v_count > 0
then
    select data into v_data from table1
end if;

Return v_data

Dies wird getan, die NO_DATA_FOUND Ausnahme zu vermeiden, sonst würde ich drei Ausnahmebehandlungsblocks muß die NO_DATA_FOUND Ausnahme für jede Tabelle Zugang zu fangen.

Zur Zeit ich dies Neuimplementierung mit Cursorn so, dass ich so etwas wie diese:

cursor C1 is
    select data from table1;
Open C1
Fetch C1 into v_data
if C1%FOUND
then
    Close C1
    Return v_data
End If

Ich wollte herausfinden, was man von einer Performance-Sicht besser ist - die eine mit Cursorn, oder eine, die eine Auswahl in eine Variable tut und hat drei NO_DATA_FOUND Ausnahmeblocks. Ich will nicht den zweistufige Abfrageprozess verwenden, die wir derzeit haben.

War es hilfreich?

Lösung

Ich weiß nicht, warum du so scharf sind die Ausnahme zu vermeiden? Was ist falsch an:

begin
    begin
        select data into v_data from table1;
    exception
        when no_data_found then
        begin
            select data into v_data from table2;
        exception
            when no_data_found then
            begin
               select data into v_data from table3;
            exception
                when no_data_found then
                    v_data := null;
            end;
        end;
    end;
    return v_data;
end;

Ich glaube, dies besser abschneiden wird als die andere Lösung, weil sie die minimal möglichen funktionierts das gewünschte Ergebnis zu erzielen.

Siehe Wie schlimm ignoriert Ausnahme Oracle DUP_VAL_ON_INDEX? , wo ich zeigen, dass Ausnahmen eine bessere Leistung als das Zählen zu sehen, ob es irgendwelche Daten.

mit

Andere Tipps

select count(*) from table1 into v_count
if v_count > 0 then
    select data into v_data from table1;
else
    v_data := null;
end if;
return v_data;

ist nicht gleichbedeutend mit

begin
    select data into v_data from table1;
    return v_data;
exception
    when no_data_found then
        return null;
end;

in einer Mehrbenutzerumgebung. Im ersten Fall, jemand in der Tabelle zwischen den Punkten aktualisieren konnte, wo man auf die Existenz überprüfen und wenn Sie die Daten gelesen werden.

Performance-weise, habe ich keine Ahnung was besser ist, aber ich weiß, dass die erste Option zwei Zusammenhang auf den SQL-Engine schaltet macht und die zweiten nur, dass ein Kontext-Switch.

Wie Sie Szenario 1 jetzt Handhabung sind nicht gut. Nicht nur tun Sie zwei Abfragen, wenn man ausreichen, aber wie Erik wies darauf hin, es eröffnet sich die Möglichkeit der Daten Wechsel zwischen den beiden Abfragen (es sei denn, Sie eine schreibgeschützte oder serializable Transaktion verwenden).

Da Sie in diesem Fall sagen, dass die Daten in genau eine der drei Tabellen sein, wie etwa das?

SELECT data
  INTO v_data FROM
  (SELECT data FROM table1
   UNION ALL
   SELECT data FROM table2
   UNION ALL
   SELECT data FROM table3
  )

Ein weiterer „Trick“ Sie können keine-Daten-Handler gefunden verwenden, um Schreiben mehr zu vermeiden wären:

SELECT MIN(data) INTO v_data FROM table1;
IF v_data IS NOT NULL THEN
   return v_data;
END IF;

SELECT MIN(data) INTO v_data FROM table2;
...etc...

, aber ich sehe nicht wirklich einen Grund, die besser ist als mit drei Ausnahmebehandler.

Für Ihr zweites Szenario, denke ich, was Sie meinen, dass es Daten in beiden Tabellen sein kann, und Sie mögen die Daten von Tabelle 1 verwenden, wenn vorhanden, andernfalls die Daten aus der Tabelle verwendet 2. Wieder Sie dies in einem einzigen tun könnte Abfrage:

SELECT data
  INTO v_data FROM
  (SELECT data FROM
    (SELECT 1 sort_key, data FROM table1
     UNION ALL
     SELECT 2 sort_key, data FROM table2
    )
   ORDER BY sort_key ASC
  )
  WHERE ROWNUM = 1

Eine erweiterte Version von "Dave Costa" 's MIN Option ...

SELECT COUNT(1), MIN(data) INTO v_rowcount, v_data FROM table2;

Jetzt kann v_rowcount für Werte 0,> 1 (größer als 1), wo normale Auswahlabfrage NO_DATA_FOUND oder TOO_MANY_ROWS Ausnahme werfen wird geprüft werden. Wert „1“ zeigt an, dass genau eine Zeile vorhanden ist, und wird unseren Zweck dienen.

DECLARE
    A VARCHAR(35);
    B VARCHAR(35);
BEGIN
    WITH t AS
    (SELECT OM_MARCA, MAGAZIA FROM ifsapp.AKER_EFECTE_STOC WHERE (BARCODE = 1000000491009))
    SELECT
    (SELECT OM_MARCA FROM t) OM_MARCA,
    (SELECT MAGAZIA FROM t) MAGAZIA
    INTO A, B
    FROM DUAL;
    IF A IS NULL THEN
       dbms_output.put_line('A este null');
    END IF;
    dbms_output.put_line(A);
    dbms_output.put_line(B);
END;
/

Verwenden der „für die Zeile in cursor“ Form einer Schleife, und die Schleife wird verarbeiten einfach nicht, wenn es keine Daten:

declare cursor
t1Cur is
 select ... from table1;
t2Cur is
 select ... from table2;
t3Cur is
 select ... from table3;
t1Flag boolean FALSE;
t2Flag boolean FALSE;
t3Flag boolean FALSE;
begin
for t1Row in t1Cur loop
  ... processing, set t1Flag = TRUE
end loop;
for t2Row in t2Cur loop
  ... processing, set t2Flag = TRUE
end loop;
for t3Row in t3Cur loop
  ... processing, set t3Flag = TRUE
end loop;
... conditional processing based on flags
end;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top