Gibt es eine Möglichkeit, eine Abfrage nur einmal auszuführen, um sie in eine Variable auszuwählen, da die Abfrage möglicherweise nichts zurückgibt? In diesem Fall sollte die Variable null sein.
Derzeit kann ich eine select into
Variable nicht direkt ausführen, da sich die Variable PL / SQL beschweren würde, wenn die Abfrage nichts zurückgibt. Ich kann die Abfrage nur zweimal ausführen, wobei die erste die Zählung durchführt. Wenn die Zählung Null ist, setzen Sie die Variable auf Null. Wenn die Zählung 1 ist, wählen Sie sie in die Variable aus.
Der Code wäre also wie folgt:
v_column my_table.column%TYPE;
v_counter number;
select count(column) into v_counter from my_table where ...;
if (v_counter = 0) then
v_column := null;
elsif (v_counter = 1) then
select column into v_column from my_table where ...;
end if;
Vielen Dank.
Update: Der Grund, warum ich keine Ausnahme verwendet habe, ist, dass ich nach dem Zuweisen der noch eine folgende Logik v_column
habe und diese goto
im Ausnahmeabschnitt verwenden muss, um zum folgenden Code zurückzukehren. Ich zögere ein bisschen mit goto
Zeilen.
v_column
und im Ausnahmeabschnitt "goto" verwenden muss, um zum folgenden Code zurückzukehren. Ich zögere ein bisschen mitgoto
Zeilen.Ich weiß, dass es ein alter Thread ist, aber ich denke immer noch, dass es sich lohnt, ihn zu beantworten.
select ( SELECT COLUMN FROM MY_TABLE WHERE .... ) into v_column from dual;
Anwendungsbeispiel:
declare v_column VARCHAR2(100); begin select (SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'DOES NOT EXIST') into v_column from dual; DBMS_OUTPUT.PUT_LINE('v_column=' || v_column); end;
quelle
ORA-00913
zu viele Werte.Was ist mit MAX? Auf diese Weise wird die Variable auf NULL gesetzt, andernfalls auf den Maximalwert, wenn keine Daten gefunden werden.
Da Sie entweder einen Wert von 0 oder 1 erwarten, sollte MAX in Ordnung sein.
v_column my_table.column%TYPE; select MAX(column) into v_column from my_table where ...;
quelle
Die Verwendung einer Cursor FOR LOOP-Anweisung ist meine bevorzugte Methode, um dies zu tun.
Dies ist sicherer als die Verwendung eines expliziten Cursors, da Sie nicht daran denken müssen, ihn zu schließen, damit Sie keine Cursor "auslaufen" können.
Sie brauchen keine "in" -Variablen, Sie müssen nicht "FETCH", Sie müssen keine "NO DATA FOUND" -Ausnahmen abfangen und behandeln.
Probieren Sie es aus, Sie werden nie zurückkehren.
v_column my_table.column%TYPE; v_column := null; FOR rMyTable IN (SELECT COLUMN FROM MY_TABLE WHERE ....) LOOP v_column := rMyTable.COLUMN; EXIT; -- Exit the loop if you only want the first result. END LOOP;
quelle
Von allen obigen Antworten scheint Björns Antwort die eleganteste und kurzeste zu sein. Ich persönlich habe diesen Ansatz oft verwendet. Die MAX- oder MIN-Funktion erledigt den Job gleich gut. Es folgt vollständiges PL / SQL, nur die where-Klausel sollte angegeben werden.
declare v_column my_table.column%TYPE; begin select MIN(column) into v_column from my_table where ...; DBMS_OUTPUT.PUT_LINE('v_column=' || v_column); end;
quelle
Ich würde empfehlen, einen Cursor zu verwenden. Ein Cursorabruf besteht immer aus einer einzelnen Zeile (es sei denn, Sie verwenden eine Massensammlung), und Cursor lösen nicht automatisch no_data_found- oder too_many_rows-Ausnahmen aus. Sie können jedoch das einmal geöffnete Cursorattribut überprüfen, um festzustellen, ob und wie viele Zeilen vorhanden sind.
declare v_column my_table.column%type; l_count pls_integer; cursor my_cursor is select count(*) from my_table where ...; begin open my_cursor; fetch my_cursor into l_count; close my_cursor; if l_count = 1 then select whse_code into v_column from my_table where ...; else v_column := null; end if; end;
Oder noch einfacher:
declare v_column my_table.column%type; cursor my_cursor is select column from my_table where ...; begin open my_cursor; fetch my_cursor into v_column; -- Optional IF .. THEN based on FOUND or NOTFOUND -- Not really needed if v_column is not set if my_cursor%notfound then v_column := null; end if; close my_cursor; end;
quelle
COUNT(*)
), öffnen Sie den Cursor und rufen Sie das Ergebnis in Ihre lokale Variable ab. Verwenden Sie dann das%FOUND
Attribut, um den gewünschten Status zu bestimmen. Auf diese Weise führen Sie die Abfrage nur einmal aus, benötigen keinen Ausnahmeblock und vermeidenSELECT .. INTO
mögliche Ausnahmen.Ich benutze diese Syntax für Flexibilität und Geschwindigkeit -
begin -- with KLUJ as ( select 0 ROES from dual union select count(*) from MY_TABLE where rownum = 1 ) select max(ROES) into has_rows from KLUJ; -- end;
Dual gibt 1 Zeile zurück, Rownum fügt 0 oder 1 Zeilen und max () Gruppen zu genau 1 hinzu. Dies ergibt 0 für keine Zeilen in einer Tabelle und 1 für eine andere Anzahl von Zeilen.
Ich erweitere die where-Klausel, um Zeilen nach Bedingung zu zählen, entferne Rownum, um Zeilen zu zählen, die eine Bedingung erfüllen, und erhöhe Rownum, um Zeilen zu zählen, die die Bedingung bis zu einem Grenzwert erfüllen.
quelle
COALESCE
gibt immer das erste Nicht-Null-Ergebnis zurück. Auf diese Weise erhalten Sie die gewünschte Anzahl oder 0:select coalesce(count(column) ,0) into v_counter from my_table where ...;
quelle