Existe-t-il un moyen de simplement exécuter une requête une fois pour la sélectionner dans une variable, sachant que la requête risque de ne rien renvoyer; dans ce cas, la variable doit être null.
Actuellement, je ne peux pas faire un select into
une variable directement, car si la requête ne renvoie rien, la variable PL/SQL se plaindrait que la variable ne soit pas définie. Je ne peux exécuter la requête que deux fois. Le premier compte et si le nombre est égal à zéro, définissez la variable sur null et si le nombre est égal à 1, sélectionnez-le dans la variable.
Donc, le code serait comme:
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;
merci.
Mise à jour: La raison pour laquelle je n'ai pas utilisé exception est que j'ai toujours une certaine logique à suivre après avoir affecté le v_column
, et que je dois utiliser goto
dans la section exception pour revenir au code suivant. Je suis un peu hésitant de goto
lignes.
Vous pouvez simplement gérer l'exception NO_DATA_FOUND
en définissant votre variable sur NULL
. De cette façon, une seule requête est requise.
v_column my_table.column%TYPE;
BEGIN
BEGIN
select column into v_column from my_table where ...;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := NULL;
END;
... use v_column here
END;
Je sais que c'est un vieux fil, mais je pense toujours qu'il vaut la peine d'y répondre.
select (
SELECT COLUMN FROM MY_TABLE WHERE ....
) into v_column
from dual;
Exemple d'utilisation:
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;
Utiliser une déclaration Cursor FOR LOOP est ma manière préférée de le faire.
Il est plus sûr d'utiliser un curseur explicite, car vous n'avez pas besoin de vous rappeler de le fermer, vous ne pouvez donc pas "laisser fuir" les curseurs.
Vous n'avez pas besoin de variables "en", vous n'avez pas besoin de "FETCH", vous n'avez pas besoin d'attraper et de gérer les exceptions "NO DATA FOUND".
Essayez, vous ne reviendrez jamais.
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;
Qu'en est-il de l'utilisation de MAX? Ainsi, si aucune donnée n'est trouvée, la variable est définie sur NULL, sinon, la valeur maximale.
Puisque vous attendez 0 ou 1 valeur, MAX devrait pouvoir être utilisé.
v_column my_table.column%TYPE;
select MAX(column) into v_column from my_table where ...;
De toutes les réponses ci-dessus, réponse de Björn semble être la plus élégante et la plus courte. J'ai personnellement utilisé cette approche plusieurs fois. La fonction MAX ou MIN fera le travail aussi bien. Complet PL/SQL suit, juste la clause where doit être spécifiée.
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;
Je recommanderais d'utiliser un curseur. Une extraction de curseur est toujours une seule ligne (sauf si vous utilisez une collection en bloc), et les curseurs ne lancent pas automatiquement les exceptions no_data_found ou too_many_rows; Cependant, vous pouvez inspecter l'attribut curseur une fois ouvert pour déterminer si vous avez une ligne et combien.
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;
Ou, encore plus simple:
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;
J'utilise cette syntaxe pour plus de flexibilité et de rapidité -
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 renvoie 1 ligne, rownum ajoute 0 ou 1 ligne et max () à exactement 1. Cela donne 0 pour aucune ligne dans une table et 1 pour tout autre nombre de lignes.
J'étend la clause where pour compter les lignes par condition, supprime rownum pour compter les lignes répondant à une condition et j'augmente rownum pour compter les lignes répondant à la condition jusqu'à une limite.