且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

插入之前检查表中非重复行的过程(Oracle)

更新时间:2023-01-22 16:32:04

您在参数列表后加了分号,而不是as.试试:

You've got a semi-colon after the list of parameters instead of as. Try:

CREATE OR REPLACE PROCEDURE add_vals (c_cntry_id OUT COUNTRIES.COUNTRY_ID%TYPE,
                                       c_cntr_name IN COUNTRIES.COUNTRY_NAME%TYPE, 
                                       c_rgn_id IN COUNTRIES.REGION_ID%TYPE)
AS
BEGIN
  INSERT INTO countries(COUNTRY_ID, COUNTRY_NAME,REGION_ID)
    values (user_seq.nextval, c_cntr_name,c_rgn_id)
  Returning country_id into c_cntry_id;
EXCEPTION
  WHEN dup_val_on_index
  THEN 
    c_cntry_id := null;
END;
/

还要注意,我已经使用returning子句来设置c_cntry_id的值.

Note also that I have used the returning clause to set the value of c_cntry_id.

查看已编辑的代码,现在的问题是,您的过程中在ISBEGIN

Looking at your edited code, the issue now is that you have got DECLARE in your procedure between the IS and the BEGIN

此外,由于您正在使用序列值将行插入表中-希望这是唯一可以插入行的点-永远不会导致dup_val_on_index异常.

Also, since you're using a sequence value to insert rows into the table - and, hopefully, this is the only point at which rows could be inserted - that shouldn't ever result in a dup_val_on_index exception.

由于在country_name列上有一个附加的唯一约束,我已经敲出了一个将创建dup_val_on_index的测试用例,并且还向您展示了两种创建代码的方法-作为过程和函数,以及演示怎么称呼他们:

I've knocked up a test case that will create the dup_val_on_index due to an additional unique constraint on the country_name column, and also shown you two ways of creating the code - as a procedure and as a function, as well as demonstrating how to call them:

drop table countries;
drop sequence user_seq;
drop procedure add_country_pr;
drop function add_country_fn;

create table countries (country_id integer primary key,
                        country_name varchar2(50) unique not null,
                        region_id integer);

create sequence user_seq
  start with 1
  maxvalue 99999
  minvalue 1
  nocycle
  cache 20
  noorder;

create or replace procedure add_country_pr (c_cntry_id out countries.country_id%type,
                                            c_cntr_name in countries.country_name%type, 
                                            c_rgn_id in countries.region_id%type)
is
begin
  insert into countries (country_id, country_name,region_id)
  values (user_seq.nextval, c_cntr_name,c_rgn_id)
  returning country_id into c_cntry_id;
exception
  when dup_val_on_index
  then 
    c_cntry_id := null;
end add_country_pr;
/

create or replace function add_country_fn (c_cntr_name in countries.country_name%type, 
                                           c_rgn_id in countries.region_id%type)
return integer
is
  v_cntry_id integer;
begin
  insert into countries (country_id, country_name,region_id)
  values (user_seq.nextval, c_cntr_name,c_rgn_id)
  returning country_id into v_cntry_id;

  return v_cntry_id;
exception
  when dup_val_on_index
  then 
    return null;
end add_country_fn;
/


set serveroutput on;

-- anonymous block used to call the above procedure/function
declare
  v_cntry_id integer;
begin
  add_country_pr (c_cntry_id => v_cntry_id, -- variable to hold the value of the out parameter
                  c_cntr_name => 'GBR', 
                  c_rgn_id => 1);
  commit;

  dbms_output.put_line('add_country_pr 1st call, country_id = "'||v_cntry_id||'"');

  add_country_pr (c_cntry_id => v_cntry_id, -- variable to hold the value of the out parameter
                  c_cntr_name => 'GBR', 
                  c_rgn_id => 1);
  commit;

  dbms_output.put_line('add_country_pr 2nd call, country_id = "'||v_cntry_id||'"');

  v_cntry_id := add_country_fn (c_cntr_name => 'USA', 
                                c_rgn_id => 2);
  commit;

  dbms_output.put_line('add_country_fn 1st call, country_id = "'||v_cntry_id||'"');

  v_cntry_id := add_country_fn (c_cntr_name => 'USA', 
                                c_rgn_id => 2);
  commit;

  dbms_output.put_line('add_country_fn 2nd call, country_id = "'||v_cntry_id||'"');
end;
/

add_country_pr 1st call, country_id = "1"
add_country_pr 2nd call, country_id = ""
add_country_fn 1st call, country_id = "3"
add_country_fn 2nd call, country_id = ""