Oracle 数据库中的批量插入失败 - 引用未初始化的集合

问题描述 投票:0回答:2

我正在开发一个在 Oracle 数据库中执行批量插入(~55k,但也可以更多)的应用程序。 下面是 SQL 脚本:-

DECLARE
    errstr VARCHAR2(4000) := '';
    errors NUMBER;
    i      NUMBER;
    er     NUMBER;
    bk1    NUMBER;
    bk2    DATE;
    bk3    VARCHAR;
    bk49   NUMBER;
BEGIN
    bk1 := :1;
    bk2 := :2;
    bk3 := :3;
    bk49 := :49;
    FORALL i IN 1..54555
        INSERT INTO table_name (
            col1,
            col2,
            col3,
            col49
        ) VALUES (
            bk1(i),
            bk2(i),
            bk3(i),
            bk49(i)
        );
END;

插入失败并出现以下错误:-

oci error 6531 (ORA-06531: Reference to uninitialized collection ORA-06512: at line 126 ORA-22160: element at index [1] does not exist ORA-06512: at line 106 )

由于有数千条记录,我无法找出哪条记录存在数据问题。 (此查询是使用 PHP 动态生成的,并使用 Oracle OCI8 执行的

:1
:2
...、
:49
是绑定变量,并作为数组动态传递,如下所示:

:1 - [1, 2, 3, ..., 54555]

:2 - ["09/30/2023", "09/30/2023", "09/30/2023", ..., "09/30/2023"]

...

:49 - [1, 2, 3, ..., 54555]

有人可以帮助我了解哪个字段失败了,以及如何调试/打印导致脚本失败的特定记录数据吗? 非常感谢您的帮助。谢谢!

php sql database oracle plsql
2个回答
1
投票

如异常所示,您尚未初始化集合。

假设

:1
:2
:3
:49
是绑定变量,并且您正在绑定包中定义的 PL/SQL 关联数组。根据
oci_bind_array_by_name
文档
,您可以使用类似的东西(未经测试,因为我没有 PHP 环境):

$stid = oci_parse(
  $conn,
  "DECLARE
    errstr VARCHAR2(4000) := '';
    errors NUMBER;
    i      NUMBER;
    er     NUMBER;
    bk1    acct_common.type_tabnumber;
    bk2    acct_common.type_tabnumber;
    bk3    acct_common.type_tabnumber;
    bk49   acct_common.type_tabnumber;
BEGIN
    bk1 := :1;
    bk2 := :2;
    bk3 := :3;
    bk49 := :49;
    FORALL i IN INDICES OF bk1
        INSERT INTO table_name (
            col1,
            col2,
            col3,
            col49
        ) VALUES (
            bk1(i),
            DATE '1970-01-01' + bk2(i) * INTERVAL '1' SECOND,
            bk3(i),
            bk49(i)
        );
END;"
);
$bk1s  = array(1,2,3,4,5);
$bk2s  = array(
           mktime(0, 0, 0, 1, 1, 2023),
           mktime(0, 0, 0, 1, 2, 2023),
           mktime(0, 0, 0, 1, 3, 2023),
           mktime(0, 0, 0, 1, 4, 2023),
           mktime(0, 0, 0, 1, 5, 2023)
         );
$bk3s  = array(6,7,8,9,10);
$bk49s = array(11,12,13,14,15);
oci_bind_array_by_name($stid, ":1",  $bk1s,  5, -1, SQLT_INT);
oci_bind_array_by_name($stid, ":2",  $bk2s,  5, -1, SQLT_INT);
oci_bind_array_by_name($stid, ":3",  $bk3s,  5, -1, SQLT_INT);
oci_bind_array_by_name($stid, ":49", $bk49s, 5, -1, SQLT_INT);
oci_execute($stid);

0
投票

集合将像下面的示例一样被初始化:

declare
  type t_tab_n is table of number;
  tab_n t_tab_n;
begin
  tab_n:=t_tab_n(1,3,12,13,33,44);
end;

前面的示例将使用多个元素初始化集合。 或者它可能是这样的:

declare
  type t_tab_n is table of number;
  tab_n t_tab_n;
begin
  tab_n:=t_tab_n(); -- initialize collection with no elements
  tab_n.extend; --- add one element to collection
  tab_n(tab_n.last):=3; --- assign value to the added element
  tab_n.extend;
  tab_n(tab_n.last):=12;
end;

您可能无法像您希望的那样将集合作为简单的绑定变量传递。这是来自 Oracle 方面的。至于向 Oracle 发送数据的客户端应用程序,我不知道如何批量绑定集合。

© www.soinside.com 2019 - 2024. All rights reserved.