【问题标题】:Data not added accurately through stored procedure (Oracle 11g R2)未通过存储过程准确添加数据 (Oracle 11g R2)
【发布时间】:2017-10-19 03:59:10
【问题描述】:

我有一个临时表,其中的数据是通过 sqlldr 加载的。临时表中的数据添加如下:

PHONE       ADDRESS     ORDER_ID
9971410000  D-166 GF    1
9910020000  H-12D       2
9873120000  K-19C       3
9811120000  J-200       4
9873120000  K-19C       5
9810320000  N-29B       6
9810390000  J-235 GF    7
9873500000  M-39        8
8447910000  J-62 GF     9
9873120000  K-19C       10

数据插入到'temp'表后,触发器调用一个过程插入到其他表中:

 create or replace TRIGGER insert_customer
 AFTER INSERT ON temp
 FOR EACH ROW
 BEGIN
   insert_address(:new.phno, :new.addr, :new.ord_id);
 END;

程序如下:

   create or replace procedure INSERT_ADDRESS(
   p_cust_phone customer.cust_phone%type, 
   p_address address.address%type, 
   p_ord_id customer_order.order_id%type
   )
   is
   l_cust_id customer.cust_id%type;
   l_address_id address.address_id%type;
   begin
     begin
      select cust_id 
      into l_cust_id 
      from customer c
      where c.cust_phone=p_cust_phone;
    exception
      when no_data_found then
      insert into customer 
      values (cust_id_seq.nextval, 'No Name', p_cust_phone)
      returning cust_id into l_cust_id;
    end;

      select address_id
      into l_address_id
      from address a
      where a.address=p_address;
  exception
      when no_data_found then
      insert into address
      values (address_id_seq.nextval, UPPER(p_address), UPPER(p_area))
      returning address_id into l_address_id;

  insert into customer_address
  values (l_cust_id, l_address_id);

  insert into customer_order (order_id, cust_id)
  values (p_ord_id,l_cust_id);

  end;

CUSTOMER_ORDER 表中插入的数据不正确。下面列出了我在以下查询中得到的结果:

select * from customer_order;

ord_id   cust_id
1         1
2         2
3         3
4         4
6         5
7         6
8         7
9         8

order_id (5,10) 丢失,因为它们与 ord_id=3 来自同一客户。同一客户的多个订单不会添加到 customer_order 表中。我无法理解我在哪里犯了错误?

【问题讨论】:

    标签: stored-procedures oracle11g


    【解决方案1】:

    问题在于,只有当传入的地址在地址表中不存在时,您才会插入 customer_order - 您已在 insert_address 过程的异常子句中得到它。

    我会做的是创建一个包,然后将获取/存储客户和地址详细信息的步骤作为单独的函数。这样,您会更容易理解代码,从而更容易维护、调试等。

    类似:

    CREATE OR REPLACE PACKAGE BODY customer_pkg
    AS
      FUNCTION get_customer_id (p_cust_phone customer.cust_phone%TYPE)
      RETURN customer.cust_id%TYPE
      IS
        l_cust_id customer.cust_id%TYPE;
      BEGIN
        SELECT cust_id
        INTO   l_cust_id
        FROM   customer
        WHERE  cust_phone = p_cust_phone;
    
      EXCEPTION
        WHEN no_data_found THEN
          INSERT INTO customer (cust_id, cust_name, cust_phone)
          VALUES (cust_id_seq.nextval, 'No Name', p_cust_phone)
          RETURNING cust_id INTO l_cust_id;
      END get_customer_id;
    
      FUNCTION get_address_id (p_address address.address%TYPE)
      RETURN address.address_id%TYPE
      IS
        l_address_id address.address_id%TYPE;
      BEGIN
        SELECT address_id
        INTO   l_address_id
        FROM   address
        WHERE  address = p_address;
    
      EXCEPTION
        WHEN no_data_found THEN
          INSERT INTO address (address_id, address)
          VALUES (address_id_seq.nextval, p_address)
          RETURNING address_id INTO l_address_id;
      END get_address_id;
    
      PROCEDURE insert_order(p_cust_phone customer.cust_phone%TYPE,
                             p_address    address.address_i%TYPE,
                             p_ord_id     customer_order.order_id%TYPE)
      IS
        l_cust_id customer.cust_id%TYPE;
        l_address_id address.address_id%TYPE;
      BEGIN
        l_cust_id := get_customer_id (p_cust_phone => p_cust_phone);
        l_address_id := get_address_id (p_address => p_address);
    
        INSERT INTO customer_order (order_id, cust_id)
        VALUES (p_ord_id, l_cust_id);
      END insert_order;
    
    END customer_pkg;
    /
    

    那么您的触发器将如下所示:

    create or replace TRIGGER insert_customer
     AFTER INSERT ON temp
     FOR EACH ROW
     BEGIN
       customer_pkg.insert_order(p_cust_phone => :new.phno,
                                 p_address => :new.addr,
                                 p_ord_id => :new.ord_id);
     END insert_customer;
    

    【讨论】:

    • 您的程序是正确的,但它遗漏了一件事。你在哪里添加行到'CUSTOMER'和'ADDRESS'之间的连接表'CUSTOMER_ADDRESS'表中。cust_id和address_id也将插入到CUSTOMER_ADDRESS表中以便链接它们。
    • 我相信您可以查看我的程序并确定您需要在哪里添加额外的插入。
    • 'l_cust_id' 和 'l_address_id' 的值需要一起在 CUSTOMER_ADDRESS 上执行插入。由于两者的功能不同,我该如何使用它们?这就是问题,因为我使用相同的过程插入所有表。我对 pl/sql 比较陌生。
    • 所以,我猜想插入 customer_address 需要在 get_address_id 函数中进行。提示:向函数或过程添加另一个参数很容易...
    • 哦,好的,知道了。谢谢:D
    猜你喜欢
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 1970-01-01
    • 2017-09-26
    • 2014-05-07
    • 1970-01-01
    相关资源
    最近更新 更多