当结果可能为空时如何在PL / SQL中select一个variables?

有没有办法只运行一次查询来select一个variables,考虑到查询可能什么都不返回,那么在这种情况下,variables应该是空的。

目前,我不能直接select into一个variables,因为如果查询什么都没有返回,PL / SQL会抱怨variables没有被设置。 我只能运行查询两次,第一次执行计数,如果计数为零,则将variables设置为空,如果计数为1,则selectvariables。

所以代码会是这样的:

 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; 

谢谢。

更新:我没有使用exception的原因是我分配v_column后仍然有一些以下的逻辑,我必须使用goto到exception部分跳转到下面的代码。 我有点犹豫不决。

您可以简单地通过将您的variables设置为NULL来处理NO_DATA_FOUNDexception。 这样,只需要一个查询。

  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; 

我知道这是一个古老的线索,但我仍然认为这是值得回答的。

 select ( SELECT COLUMN FROM MY_TABLE WHERE .... ) into v_column from dual; 

使用示例:

 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; 

使用游标FOR LOOP语句是我最喜欢的方法。

这比使用明确的游标更安全,因为你不需要记住closures它,所以你不能“泄漏”游标。

你不需要“进入”variables,你不需要“取得”,你不需要捕捉和处理“没有数据find”exception。

试试吧,你永远不会回头。

 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; 

我会build议使用游标。 游标读取总是单行(除非使用批量集合),游标不会自动抛出no_data_found或too_many_rowsexception; 虽然你可能会检查游标属性一旦打开,以确定你是否有一个行和多less。

 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; 

或者更简单:

  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; 

怎么样使用MAX? 那样如果没有数据被发现variables被设置为NULL,否则最大值。
既然你期望0或1值,MAX应该可以使用。

 v_column my_table.column%TYPE; select MAX(column) into v_column from my_table where ...; 

我使用这个语法的灵活性和速度 –

  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; 

双返回1行,rownum添加0或1行,并且max()组精确到1.这给了0表中没有行,1表示任何其他数量的行。

我扩展了where子句来按条件对行进行计数,删除rownum来计算符合条件的行数,并增加rownum来计算满足条件的行数达到极限。

从上面的所有答案中, Björn的答案似乎是最优雅和最短的。 我个人多次使用这种方法。 MAX或MINfunction将同样做好工作。 完整的PL / SQL如下,只需要指定where子句。

 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; 

COALESCE将总是返回第一个非空结果。 通过这样做,你会得到你想要的数量或0:

selectcoalesce(count(column),0)到my_table的v_counter中,其中…;