【问题标题】:Procedure to check for non-existing values in a foreign table oracle检查外部表 oracle 中不存在值的过程
【发布时间】:2015-12-02 04:35:38
【问题描述】:

我的要求是编写一个在 COUNTRIES 表中添加值的过程。但是,首先它应该检查对应的值是否存在于另一个表中,REGIONS 因为它是一个外键。仅当值存在时才允许插入 COUNTRIES 表。否则,没有。

我写了一段代码,但它抛出了一堆错误:

ORA-00950 缺少关键字 PLS-00103 遇到符号 THEN when 期待以下之一:(开始案例声明和异常 exit) (一个绑定变量) (继续关闭当前删除获取锁)

我写了这段代码:

CREATE OR REPLACE PROCEDURE addi1 (c_cntry_id IN OUT COUNTRIES.COUNTRY_ID%TYPE,
                                       c_cntr_name IN COUNTRIES.COUNTRY_NAME%TYPE, 
                                       c_rgn_id IN COUNTRIES.REGION_ID%TYPE)
IS
l_exst number(1);

begin
  select case 
           when exists
(   select r.region_id from regions r where r.region_id  IN
(SELECT REGION_ID from regions)

                        );
           then 1
           else 0
         end  into l_exst


  if l_exst = 1 
  then
    INSERT INTO countries(COUNTRY_ID, COUNTRY_NAME,REGION_ID)
    values (c_cntry_id, c_cntr_name,c_rgn_id);
  else
    DBMS_OUTPUT.put_line('YOU CANNOT'); 
  end if;
end;
/

有人可以指导我做错了什么以及如何修改查询吗?

【问题讨论】:

    标签: oracle stored-procedures foreign-keys


    【解决方案1】:

    这不是强制执行外键的正确方法。它在多用户环境中不起作用,因为我们无法看到其他用户在他们未提交的会话中正在做什么。因此,当其他用户即将提交删除时,您的代码可能会找到一个 REGION,或者相反,当其他用户即将提交插入时,您的代码可能无法找到一个 REGION。

    最好留给 Oracle 的内置功能。

    1. 定义(并启用!)REGION 和 COUNTRIES 之间的实际外键约束。
    2. 只需插入 COUNTRIES 表即可。
    3. 在异常块中处理外键违规。

    此解决方案使用 PRAGMA EXCEPTION_INIT 来为此目的定义特定异常。 Find out more.

    create or replace procedure addi1 (c_cntry_id in out countries.country_id%type,
                                           c_cntr_name in countries.country_name%type, 
                                           c_rgn_id in countries.region_id%type)
    is
        region_not_found exception;
        pragma exception_init(region_not_found, -2291);
    begin
        insert into countries(country_id, country_name,region_id)
        values (c_cntry_id, c_cntr_name,c_rgn_id);
    exception
        when region_not_found then
            dbms_output.put_line(c_rgn_id||' is not a valid REGION id'); 
            raise;
    end addi1;
    /
    

    注意它会引发异常;这意味着调用程序知道插入失败,因此可以对其下一步做出明智的选择。


    为了完整起见,这里是检查记录是否存在的语法。

    create or replace procedure addi1 (c_cntry_id in out countries.country_id%type,
                                           c_cntr_name in countries.country_name%type, 
                                           c_rgn_id in countries.region_id%type)
    is
        region_exists pls_integer;
    begin
        begin
            select 1 into region_exists
            from regions r 
            where r.region_id = c_rgn_id;
        exception
            when no_data_found then
                region_exists := 0;
        end;
        if region_exists = 1 then
             ...
    

    但正如我所说,不要这样做。


    ",它给了我 ORA-00001"

    很明显,您已经定义了 ID 为 'Ff' 的 COUNTRIES 记录。如果你想干净地处理异常,可以使用预定义的 DUP_VAL_ON_INDEX 异常:

         when DUP_VAL_ON_INDEX then
             dbms_output.put_line('There is an existing COUNTRIES record with an ID of' || c_cntry_id); 
    

    在现实生活中,我们应该始终引发异常:决定错误的严重程度是调用程序的特权。但是,如果您愿意,可以随意隐藏错误。

    【讨论】:

    • 谢谢,我运行了你的第一个程序,当我执行时,它给了我 ORA-00001(唯一键约束)。现在我不想要任何 ORA 异常。只有我定义的那些(region_not_found例外)。我正在执行这样的过程:DECLARE outputValue CHAR(2) := 'Ff';开始 addi1(outputValue,'JustKii',5);结尾; /
    【解决方案2】:

    只是为了回答你的语法问题:

    你总是从某事中选择。您的查询中缺少 from 并且有一个 ;在它的中间。

    select case
                 when exists (select r.region_id
                         from regions r
                        where r.region_id in (select region_id
                                                from regions)
    
                       ) then
                  1
                 else
                  0
              end
         into l_exst
         from dual;
    

    这部分查询有些奇怪:

    select r.region_id
    from regions r
    where r.region_id in (select region_id
                          from regions)
    

    你认为in部分是必要的吗?

    【讨论】:

    • 是的,否则,我怎么知道region_id是否存在于regions表中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多