【问题标题】:Oracle PL/SQL: Return true if column has at least "one null value" or "no data found"Oracle PL/SQL:如果列至少有“一个空值”或“未找到数据”,则返回 true
【发布时间】:2021-06-04 18:12:11
【问题描述】:

如果列至少有一个值为 null 或没有找到任何外键列值的数据,如何返回 TRUE? 尝试在互联网上搜索答案,但找不到任何与此组合相关的答案。因此将其发布在这里。
下面是数据: 表名 - MY_EMP

+----+------------+-----------+---------------------------+--------+
| id | first_name | last_name |           email           | fk_col |
+----+------------+-----------+---------------------------+--------+
|  1 | Hurleigh   | Stove     |                           |      1 |
|  2 | Joline     |           |                           |      1 |
|  3 | Martynne   | Honatsch  | mhonatsch2@infoseek.co.jp |      2 |
|  4 | Willyt     | Fullylove | wfullylove3@hhs.gov       |      2 |
|  5 | Joelly     |           | jferriday4@twitpic.com    |      3 |
+----+------------+-----------+---------------------------+--------+
  • 如果任何 fk_col 的 last_name 为 null 或 email 为 null,则返回 true
  • 如果 last_name 为 null 或 email 为 null 且 fk_col 无效,则返回 true
  • 否则返回 False

尝试编写函数并正在测试代码。这是进入函数的代码:

DECLARE
    v_verify NUMBER(2);
BEGIN
    SELECT DISTINCT 1
    INTO   v_verify
    FROM   my_emp
    WHERE  ( last_name IS NULL
              OR email IS NULL )
           AND fk_col = :custom_fk;
    dbms_output.Put_line('Return True');
EXCEPTION
    WHEN no_data_found THEN
      dbms_output.Put_line('Return False');
END; 

当参数 :custom_fk = 1 则值返回 TRUE(正确)
当参数 :custom_fk = 2 时,值返回 FALSE(正确)
当参数 :custom_fk = 700 时,值返回 FALSE(根据我的要求不正确)——在这里我希望值返回 true,但无法弄清楚如何调整代码以符合我的要求。

希望我能在这里得到一些帮助。
下面是创建表和插入数据的代码:

/* CREATE TABLE */
CREATE TABLE MY_EMP(
id NUMBER(5) NOT NULL,
first_name VARCHAR2(100) NOT NULL,
last_name VARCHAR2(100),
email VARCHAR2(100),
fk_col NUMBER(5),
CONSTRAINT "MY_EMP_PK" PRIMARY KEY ("ID")
);

/*Insert data*/
INSERT INTO my_emp(id, first_name, last_name, email, fk_col)
VALUES(1, 'Hurleigh', 'Stove', '', 1);

INSERT INTO my_emp(id, first_name, last_name, email, fk_col)
VALUES(2, 'Joline', '', '', 1);

INSERT INTO my_emp(id, first_name, last_name, email, fk_col)
VALUES(3, 'Martynne', 'Honatsch', 'mhonatsch2@infoseek.co.jp', 2);

INSERT INTO my_emp(id, first_name, last_name, email, fk_col)
VALUES(4, 'Willyt', 'Fullylove', 'wfullylove3@hhs.gov', 2);

INSERT INTO my_emp(id, first_name, last_name, email, fk_col)
VALUES(5, 'Joelly', '', 'jferriday4@twitpic.com', 3);

谢谢,
里查

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    这样可以吗?

    SQL> with temp as
      2    (select count(*) cnt
      3     from (select distinct 1 as val
      4              from my_emp
      5              where fk_col = &&par_fk_col
      6                and (   last_name is null
      7                     or email is null
      8                    )
      9           union all
     10           select distinct 2
     11              from my_emp
     12              where fk_col = &&par_fk_col
     13          )
     14    )
     15  select case when cnt = 1 then 'false'
     16              else 'true'
     17         end as result
     18  from temp;
    

    结果

    Enter value for par_fk_col: 1
    
    RESUL
    -----
    true
    
    SQL> undefine par_fk_col
    SQL> /
    Enter value for par_fk_col: 2
    
    RESUL
    -----
    false
    
    SQL> undefine par_fk_col
    SQL> /
    Enter value for par_fk_col: 3
    
    RESUL
    -----
    true
    
    SQL> undefine par_fk_col
    SQL> /
    Enter value for par_fk_col: 700
    
    RESUL
    -----
    true
    
    SQL>
    

    这就是select 声明中的全部内容。如果您正在编写一个函数,检查fk_col 是否存在于单独的查询中可能更简单;如果没有,请立即返回true。如果是,则检查其他条件。

    (顺便说一句,感谢您提供测试用例。我非常惊讶的情况非常罕见!)


    [编辑] 将该语句“转换”为 PL/SQL 并不难。我建议使用 function,而不是匿名 PL/SQL 块。

    SQL> create or replace function f_test (par_fk_col in my_emp.fk_col%type)
      2    return varchar2
      3  is
      4    retval varchar2(10);
      5  begin
      6    with temp as
      7       (select count(*) cnt
      8        from (select distinct 1 as val
      9                 from my_emp
     10                 where fk_col = par_fk_col
     11                   and (   last_name is null
     12                        or email is null
     13                       )
     14              union all
     15              select distinct 2
     16                 from my_emp
     17                 where fk_col = par_fk_col
     18             )
     19       )
     20     select case when cnt = 1 then 'false'
     21                 else 'true'
     22            end
     23     into retval
     24     from temp;
     25
     26     return retval;
     27  end;
     28  /
    
    Function created.
    

    测试:

    SQL> select f_test(1) from dual;
    
    F_TEST(1)
    ---------------------------------------
    true
    
    SQL> select f_test(2) from dual;
    
    F_TEST(2)
    ---------------------------------------
    false
    
    SQL> select f_test(700) from dual;
    
    F_TEST(700)
    ---------------------------------------
    true
    
    SQL>
    

    【讨论】:

    • 非常感谢您的帮助。如果我按原样运行代码,它就可以正常工作。如果我将此代码放在以 par_fk_col 作为输入参数的函数中,则会导致错误。无法弄清楚如何在 pl/sql 块中添加它
    • 不客气。我编辑了答案并添加了一个 PL/SQL 选项。看看吧。
    • 再次感谢您的时间和帮助。有效。早些时候,我将 select into 子句放在不同的 select 语句中。现在明白了并理解了它的功能。非常感谢您的帮助。将答案标记为已解决。
    • 没问题,如果有帮助我很高兴。
    【解决方案2】:
    SELECT case when count(*)=1 then 'true' else 'false' end ret_value
    from dual
    where not exists(
       SELECT null
       FROM   my_emp
       WHERE  fk_col = :custom_fk
       having count(*)>0
          and count(*)=count(last_name) 
          and count(*)=count(email)
    );
    

    例子:

    SQL> ho cat tests/2.sql
    SELECT case when count(*)=1 then 'true' else 'false' end ret_value
    from dual
    where not exists(
       SELECT null
       FROM   my_emp
       WHERE  fk_col = &1
       having count(*)>0
          and count(*)=count(last_name)
          and count(*)=count(email)
    );
    SQL> @tests/2.sql 1
    
    RET_V
    -----
    true
    
    SQL> @tests/2.sql 2
    
    RET_V
    -----
    false
    
    SQL> @tests/2.sql 3
    
    RET_V
    -----
    true
    
    SQL> @tests/2.sql 700
    
    RET_V
    -----
    true
    

    【讨论】:

    • 非常感谢您的解决方案。如果我按原样运行代码,它工作正常。但是,如果我在 pl/sql 块中运行此查询,则所有值都为 True。下面是代码: 声明 v_verify varchar(20);当 count()=1 时开始 SELECT 情况,然后 'true' 否则 'false' 结束 ret_value 到 v_verify 从 dual where 不存在(SELECT null FROM my_emp WHERE fk_col = :custom_fk 有 count()>0 和count()=count(last_name) 和 count()=count(email)); dbms_output.put_line('返回真');异常时 no_data_found 然后 dbms_output.put_line('Return False');结束;
    • 只需使用Dbms_output.put_line(v_verify) 。你不需要那里的异常处理程序
    • 当然@Sayan Malakshinov。现在明白了。谢谢你纠正我。非常感谢您的帮助。
    • 将您的答案转换为功能。创建或替换函数 myemp_test (fk_col_val in my_emp.fk_col%type) return varchar2 is col_val varchar2(5);当 count()=1 时开始 SELECT 情况,然后 'true' 否则 'false' 结束 ret_value 到 col_val 从 dual where 不存在(SELECT null FROM my_emp WHERE fk_col = :custom_fk 有 count()>0 和count()=count(last_name) 和 count()=count(email));返回 col_val; --dbms_output.put_line(col_val);结束;
    猜你喜欢
    • 2012-10-31
    • 1970-01-01
    • 2022-01-20
    • 2021-02-21
    • 1970-01-01
    • 2015-04-06
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多