在Oracle PL/SQL循环索引变量';中执行存储过程时出错;I';使用无效

在Oracle PL/SQL循环索引变量';中执行存储过程时出错;I';使用无效,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,我对Oracle PL/SQL相当陌生,我正在尝试执行一个存储过程,该过程将插入到orders表中,并循环将一组项目插入到order\u item表中。我已经创建了一个已定义的类型,但是当我尝试执行我的过程时,我得到了这个循环索引变量'I'use无效 SQL> -- Execute procedure SQL> DECLARE 2 order_id_ NUMBER; 3 4 BEGIN 5 insert_order(p_order_id => 4,

我对Oracle PL/SQL相当陌生,我正在尝试执行一个存储过程,该过程将插入到
orders
表中,并循环将一组项目插入到
order\u item
表中。我已经创建了一个已定义的类型,但是当我尝试执行我的过程时,我得到了这个
循环索引变量'I'use无效

SQL> -- Execute procedure
SQL> DECLARE
  2  order_id_ NUMBER;
  3
  4  BEGIN
  5      insert_order(p_order_id => 4, p_order_num => 'O223PS56', p_name => 'Test Test', p_email => 'test@test.co.uk', p_address => '123 Test Street', p_city => 'Newcastle Upon Tyne', p_province => 'Tyne and Wear', p_postcode => 'NE98 4TN', p_telephone => '123456789', p_total => 7.97, p_order_date => to_date('11-apr-2021', 'DD-mon-YYYY'));
  6      FOR i IN i..order_items
  7      LOOP
  8        insert_order_items(order_id_, order_items(i) => 5, order_items(i) => 2, order_items(i) => 2, order_items(i) => 3073748221, order_items(i) => 2, order_items(i) => 'Brand New', order_items(i) => 1.99, order_items(i) => 1.99);
  9       COMMIT;
 10     END LOOP;
 11  END;
 12  /
    FOR i IN i..order_items
             *
ERROR at line 6:
ORA-06550: line 6, column 14:
PLS-00364: loop index variable 'I' use is invalid
ORA-06550: line 6, column 5:
PL/SQL: Statement ignored
SQL>

您正在声明一个过程,并将其作为函数调用。这就是它不起作用的原因

试试这个:

DECLARE
order_id_ NUMBER;

BEGIN
    -- note here that you're now assigning the return value to anything
    insert_order(p_order_id => 4, p_order_num => 'O223PS56', p_name => 'Test Test', p_email => 'test@test.co.uk', p_address => '123 Test Street', p_city => 'Newcastle Upon Tyne', p_province => 'Tyne and Wear', p_postcode => 'NE98 4TN', p_telephone => '123456789', p_total => 7.97, p_order_date => to_date('11-apr-2021', 'DD-mon-YYYY'));
    FOR i IN 1..order_items
    LOOP
      insert_order_items(order_id_, order_items(i) => 5, order_items(i) => 2, order_items(i) => 2, order_items(i) => 3073748221, order_items(i) => 2, order_items(i) => 'Brand New', order_items(i) => 1.99, order_items(i) => 1.99);
     COMMIT;
   END LOOP;
END;
/
这:

没有意义
i
是循环变量,因此它不能同时是范围。你可以做:

for i in order_items.FIRST..order_items.LAST
或者,由于这不是稀疏数组,可能更简单:

for i in 1..order_items.COUNT loop
但是,
order\u items
是一个类型,您不能迭代类型。您将迭代集合类型的实例。您尚未声明或填充该类型的变量。在循环中,对类型的引用没有意义,如果它是实例,也没有意义

据我所知,你正在尝试这样做:

DECLARE
  order_id_ NUMBER;
  order_items_ order_items;
BEGIN
...
  -- create and populate instance of the collection type
  order_items_ := new order_items(
    order_items_collection(5, 2, 2, 3073748221, 2, 'Brand New', 1.99, 1.99)
  );

  -- iterate over the collection type
  for i in 1..order_items_.COUNT loop
    insert_order_items(
      p_order_item_id => order_id_,            -- these two values might be reversed?
      p_order_id => order_items_(i).order_id,  -- 
      p_product_id => order_items_(i).product_id,
      p_seller_id => order_items_(i).seller_id,
      p_sub_order_number => order_items_(i).sub_order_number,
      p_quantity => order_items_(i).quantity,
      p_condition => order_items_(i).condition,
      p_unit_price => order_items_(i).unit_price,
      p_cost_charge => order_items_(i).cost_charge
    );
  end loop;
END;
/

这将允许您插入多个值,而无需重复过程调用,例如通过更改:

  -- create and populate instance of the collection type
  order_items_ := new order_items(
    order_items_collection(5, 2, 2, 3073748221, 2, 'Brand New', 1.99, 1.99)
  );

(尽管从中可以看出对象命名有点混乱)

使用硬编码值似乎并不比将这些值硬编码为三个过程调用容易或简单,但您的目标可能是从其他地方传递集合,比如前端应用程序。或者,您可能希望将集合传递到您的过程中,并让该过程在集合上迭代并执行插入。目前,这两个过程似乎只是让事情变得复杂了一点,并阻止您进行批量插入


在过程内部提交通常也不是一个好主意,尤其是在循环中调用相关数据的过程。如果第三个项目插入失败,那么您已经提交了订单和前两个项目的插入,因此您将处于不一致的状态。看起来所有这些插入都应该插入到相同的事务中,并作为一个单元提交(或回滚)。

修复了第一个错误,我已将I..order\u项目中的FOR改为
FOR I..code>并且我得到了此错误
循环索引变量'I'的使用无效
FOR I..order\u项目
没有意义<如果订单项目是一个数字,则代码>对于1中的I..order\u items
可能;但它稍后将被视为一个集合,因此您可能需要为I-IN-order\u items.FIRST..order\u items.LAST
添加
。但订单项似乎没有定义。该集合应该来自何处?@AlexPoole在将I IN 1.order_items更改为
时,我得到
类型名称或子类型名称的无效使用
,但order_items已被定义为类型,除非它找不到它。使用
FOR I IN-order\u items.FIRST..order\u items.LAST
必须声明
组件“FIRST”,但您需要该类型的实例,即该类型的变量,该变量已填充了要在循环中引用的数据。但是,您在循环中所做的事情没有意义。为什么您有这样的类型和集合-过程不使用它?现在还不清楚您想做什么。所以我想做的是执行
insert\u order
过程,将数据填充到
orders
表中,然后执行另一个过程
insert\u order\u items
,但是一个订单可能有多个订单项。因此,我正在尝试创建一个过程,该过程创建一个名为
insert\u order
的订单,以及另一个在循环中调用的过程,以插入
order\u item
行。对于订单和单个项目,您有硬编码的值。可能您想要传入一组项目,也可能是订单本身的一个对象;但这不是你目前正在做的。这是我一直在寻找的,我用一个单一项目和多个项目进行了一些测试,效果非常好。谢谢你的帮助,真的很感激。
for i in 1..order_items.COUNT loop
DECLARE
  order_id_ NUMBER;
  order_items_ order_items;
BEGIN
...
  -- create and populate instance of the collection type
  order_items_ := new order_items(
    order_items_collection(5, 2, 2, 3073748221, 2, 'Brand New', 1.99, 1.99)
  );

  -- iterate over the collection type
  for i in 1..order_items_.COUNT loop
    insert_order_items(
      p_order_item_id => order_id_,            -- these two values might be reversed?
      p_order_id => order_items_(i).order_id,  -- 
      p_product_id => order_items_(i).product_id,
      p_seller_id => order_items_(i).seller_id,
      p_sub_order_number => order_items_(i).sub_order_number,
      p_quantity => order_items_(i).quantity,
      p_condition => order_items_(i).condition,
      p_unit_price => order_items_(i).unit_price,
      p_cost_charge => order_items_(i).cost_charge
    );
  end loop;
END;
/
  -- create and populate instance of the collection type
  order_items_ := new order_items(
    order_items_collection(5, 2, 2, 3073748221, 2, 'Brand New', 1.99, 1.99)
  );
  -- create and populate instance of the collection type
  order_items_ := new order_items(
    order_items_collection(5, 2, 2, 3073748221, 2, 'Brand New', 1.99, 1.99),
    order_items_collection(6, 3, 4, 3073748222, 1, 'Used', 19.99, 19.99),
    order_items_collection(7, 8, 9, 3073748223, 7, 'Refurb', 9.99, 9.99)
  );