运行 使用嵌套表的存储过程时调用的参数数量或类型错误

Wrong number or types of arguments in call when running stored procedure which uses nested tables

我的存储过程 运行 有问题,因为 returns 这个错误。我已经检查了这些值,所有这些值似乎都是正确的数据类型,所以我不确定为什么在调用该过程时它没有执行。我知道你可以为我正在做的事情创建单独的过程,但我已经设置的任务需要使用嵌套表。

错误

ORA-06550: line 19, column 7:
PLS-00306: wrong number or types of arguments in call to 'ORDER_ITEM'
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored

Table 和类型

CREATE OR REPLACE TYPE order_item AS object(
      order_item_id INT,
    order_id INT, 
    product_id INT,
    seller_id INT, 
    sub_order_number CHAR(10),
    quantity INT, 
    condition CHAR(100),
    unit_price NUMBER, 
    cost_charge NUMBER
);
/

CREATE OR REPLACE TYPE order_items AS Table of order_item;
/

CREATE TABLE Orders (
 order_id INT CONSTRAINT PKEY_order PRIMARY KEY,
 order_number CHAR(10),
 billing_name CHAR(100),
 billing_email CHAR(100),
 billing_address VARCHAR2(100),
 billing_city VARCHAR2(100),
 billing_province VARCHAR2(100),
 billing_postcode VARCHAR2(100),
 billing_telephone NUMBER(25),
 billing_total NUMBER,
 order_date DATE,
 Items order_items)
 Nested Table Items Store As Orders_Item
/

存储过程

CREATE OR REPLACE PROCEDURE insert_new_order
(
    p_order_id IN INT, 
    p_order_num IN CHAR,
    p_name IN CHAR,
    p_email IN CHAR,
    p_address IN VARCHAR2, 
    p_city IN VARCHAR2,
    p_province IN VARCHAR2,
    p_postcode IN VARCHAR2,
    p_telephone IN NUMBER, 
    p_total IN NUMBER,
    p_order_date IN DATE,
    -- Order items
    p_order_item_id IN INT, 
    p_product_id IN INT, 
    p_seller_id IN INT,
    p_sub_order_number IN CHAR, 
    p_quantity IN INT,
    p_condition IN CHAR, 
    p_unit_price IN NUMBER, 
    p_cost_charge IN NUMBER
)
AS
BEGIN
    DBMS_OUTPUT.PUT_LINE ('Insert attempted');

    INSERT INTO Orders (order_id, order_number, billing_name, billing_email, billing_address, billing_city, billing_province, billing_postcode, billing_telephone, billing_total, order_date, items)
    VALUES (p_order_id, p_order_num, p_name, p_email, p_address, p_city, p_province, p_postcode, p_telephone, p_total, p_order_date, order_items(
        order_item(p_order_item_id, p_order_id, p_product_id, p_seller_id, p_sub_order_number, p_quantity, p_condition, p_unit_price, p_cost_charge)));

    COMMIT;

    DBMS_OUTPUT.PUT_LINE ('Insert succeeded');

    EXCEPTION
     WHEN others THEN   
        DBMS_OUTPUT.PUT_LINE ('Insert rejected');
      DBMS_OUTPUT.PUT_LINE ('SQL Error Code:  ' || SQLCODE);
      DBMS_OUTPUT.PUT_LINE ('SQL Error Message:  ' || SQLERRM); 
      ROLLBACK;
END;
/

尝试调用过程时。

DECLARE
  order_id_ NUMBER;
BEGIN
  order_id_ := 2;

  insert_new_order(
    p_order_id => order_id_,
    p_order_num => 'O223PS56',
    p_name => 'Test',
    p_email => 'test@test.co.uk',
    p_address => 'test@test.co.uk',
    p_city => 'Newcastle Upon Tyne',
    p_province => 'County Durham',
    p_postcode => 'Tyne and Wear',
    p_telephone => '123456789',
    p_total => 112.95,
    p_order_date => to_date('11-apr-2021', 'DD-mon-YYYY'),
    order_items(    
      order_item(
        p_order_item_id => 5, 
        order_id_,
        p_product_id => 2, 
        p_seller_id => 2, 
        p_sub_order_number => 3073748222, 
        p_quantity => 2, 
        p_condition => 'Brand New', 
        p_unit_price => 53.49,
        p_cost_charge => 0),
      order_item(
        p_order_item_id => 6, 
        order_id_,
        p_product_id => 1, 
        p_seller_id => 1, 
        p_sub_order_number => 3073748223, 
        p_quantity => 2, 
        p_condition => 'Brand New', 
        p_unit_price => 1.99, 
        p_cost_charge => 1.99)
      )
  );
END;
/

您不想传递每个 order_item 的所有组件;只需传递数组:

CREATE OR REPLACE PROCEDURE insert_new_order
(
    p_order_id    IN ORDERS.ORDER_ID%TYPE, 
    p_order_num   IN ORDERS.ORDER_NUMBER%TYPE,
    p_name        IN ORDERS.BILLING_NAME%TYPE,
    p_email       IN ORDERS.BILLING_EMAIL%TYPE,
    p_address     IN ORDERS.BILLING_ADDRESS%TYPE,
    p_city        IN ORDERS.BILLING_CITY%TYPE,
    p_province    IN ORDERS.BILLING_PROVINCE%TYPE,
    p_postcode    IN ORDERS.BILLING_POSTCODE%TYPE,
    p_telephone   IN ORDERS.BILLING_TELEPHONE%TYPE, 
    p_total       IN ORDERS.BILLING_TOTAL%TYPE,
    p_order_date  IN ORDERS.ORDER_DATE%TYPE,
    p_items       IN ORDERS.ITEMS%TYPE
)
AS
BEGIN
    DBMS_OUTPUT.PUT_LINE ('Insert attempted');

    INSERT INTO Orders (
      order_id,
      order_number,
      billing_name,
      billing_email,
      billing_address,
      billing_city,
      billing_province,
      billing_postcode,
      billing_telephone,
      billing_total,
      order_date,
      items
    ) VALUES (
      p_order_id,
      p_order_num,
      p_name,
      p_email,
      p_address,
      p_city,
      p_province,
      p_postcode,
      p_telephone,
      p_total,
      p_order_date,
      p_items
    );

    DBMS_OUTPUT.PUT_LINE ('Insert succeeded');
END;
/

然后:

DECLARE
  order_id_ NUMBER;
BEGIN
  order_id_ := 2;

  insert_new_order(
    p_order_id => order_id_,
    p_order_num => 'O223PS56',
    p_name => 'Test',
    p_email => 'test@test.co.uk',
    p_address => 'test@test.co.uk',
    p_city => 'Newcastle Upon Tyne',
    p_province => 'County Durham',
    p_postcode => 'Tyne and Wear',
    p_telephone => '123456789',
    p_total => 112.95,
    p_order_date => to_date('11-apr-2021', 'DD-mon-YYYY'),
    p_items => order_items(    
      order_item(5, order_id_, 2, 2, 3073748222, 2, 'Brand New', 53.49, 0),
      order_item(6, order_id_, 1, 1, 3073748223, 2, 'Brand New',  1.99, 1.99)
    )
  );
  
  COMMIT;
END;
/

(注意:不要 COMMIT 在您的程序中,因为您希望能够多次调用该程序并选择是 COMMIT 它们作为批处理还是 ROLLBACK 作为一个批处理。另外,不要捕获 OTHERS 错误,因为它会掩盖很多问题并使调试变得非常困难。如果你想捕获特定的错误,那么只捕获那些特定的错误,然后让其他错误会传播,因此您知道需要调试的内容;在引发异常的情况下将有一个隐式 ROLLBACK,因此您不需要显式地这样做。)

db<>fiddle here