oracle 将大于 3 位的整数值分配给绑定变量会出现 ORA-06502 错误
oracle assigning integer value bigger than 3 digits to a bind variable gets ORA-06502 error
我需要使用 RETURING INTO
从 oracle INSERT
语句中获取生成的 id
,然后通过 zend 框架 paramContainer
对象访问该值。
如果 id
数字大于 3 位数字,我会收到此错误:
ORA-06502: PL/SQL: 错误:缓冲区 della stringa di caratteri troppo piccolo di numero o valore
这是 zend-framework
部分:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('retval', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('id_progetto', 'retval');
这是返回错误的代码:
DECLARE
id_progetto NUMBER;
retval NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (COD_FIS, MATRICOLA, STATO, STATO_INTERNO, DATA_PRESENTAZIONE, DATA_ULTIMA_MODIFICA)
VALUES (:cod_fis, :matricola, 'A', 'C', TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (ID_PROGETTO, OBIETTIVO)
VALUES (:id_progetto, :obiettivo);
:retval := :id_progetto;
END;
虽然此代码有效:
DECLARE
id_progetto NUMBER;
retval NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (COD_FIS, MATRICOLA, STATO, STATO_INTERNO, DATA_PRESENTAZIONE, DATA_ULTIMA_MODIFICA)
VALUES (:cod_fis, :matricola, 'A', 'C', TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE) RETURNING SUBSTR(id,1,3) INTO :id_progetto; /* here I'm truncating the number to 3 digits */
INSERT INTO LAVORO_TELE_OBIETTIVO (ID_PROGETTO, OBIETTIVO)
VALUES (:id_progetto, :obiettivo);
:retval := :id_progetto;
END;
谢谢,
亚历克斯
ORA-06502 可能是您尝试执行导致算术、数字、字符串、转换或约束错误的语句的结果。
- 您试图为数字变量赋值,但该值大于变量可以处理的值
- 这就是你报告的内容
- 您试图将 non-numeric 值分配给数值变量并导致转换错误
- 这里闻起来不对
如果您设法使用 substr
使其工作,是否有可能 insert
语句返回的值实际上是一个 字符串 (例如 123A
) 不能放入 NUMBER
数据类型变量?
因为,将 4 位数字存储到 non-constrained NUMBER
数据类型变量中没有问题。
SQL> declare
2 l_id_progetto number;
3 begin
4 l_id_progetto := 123456789;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
此外,这就是你正在做的(简化):
DECLARE
id_progetto NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (...)
RETURNING id INTO :id_progetto;
^
|
what is this colon doing here?
不应该吗
returning id into id_progetto
相反?看起来你正在将它插入到......嗯,这个 PL/SQL 程序之外的东西(例如 Oracle Forms 字段,Apex 页面项目,实际上 是 能够仅包含 3 个字符,但 - 不是本地声明的变量)。
您正在混合在 DECLARE
子句中定义的局部 PL/SQL 变量和前缀为 :
的全局定义的绑定变量。尽管它们可能具有相同的标识符,但它们不是同一个变量。
您可能想要的是:
DECLARE
id_progetto NUMBER; -- local variable
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE
) RETURNING id INTO id_progetto; -- into the local variable
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
id_progetto, :obiettivo -- read the local variable
);
:retval := id_progetto; -- out into the global bind variable
END;
可能using:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('retval', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('retval', 'retval');
或者,不使用任何局部变量:
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE
) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
:id_progetto, :obiettivo
);
END;
然后:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('id_progetto', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('id_progetto', 'id_progetto');
你也不应该将日期作为字符串传递,而应该只使用 DATE
数据类型(在 Oracle 中,DATE
总是有一个时间部分;这可能意味着 Zend 中的等价物是时间戳数据类型而不是日期)。
如果您确实将其作为 Oracle DATE
传递,那么您的代码将变为:
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
:dataPresentazione,
SYSDATE
) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
:id_progetto, :obiettivo
);
END;
并且您不想在 Zend 代码中使用 ::TYPE_AUTO
,而是指定绑定变量的实际类型(如果 Zend 支持 ::TYPE_DATE
或 ::TYPE_TIMESTAMP
,这并不明显它确实如此)。
对于您的 Zend 代码,您要确保您使用的 id_progetto
and/or retval
中的任何一个被声明为 OUT
或 IN/OUT
参数绑定变量而不是 IN
参数。
从 this bug 开始,您似乎需要在同一个绑定参数上同时使用 offsetSet
和 offsetSetReference
(但 Zend/Lamina 文档在描述了这些方法应该做什么,但没有给出明显识别 OUT
或 IN/OUT
绑定变量的实际示例。
我需要使用 RETURING INTO
从 oracle INSERT
语句中获取生成的 id
,然后通过 zend 框架 paramContainer
对象访问该值。
如果 id
数字大于 3 位数字,我会收到此错误:
ORA-06502: PL/SQL: 错误:缓冲区 della stringa di caratteri troppo piccolo di numero o valore
这是 zend-framework
部分:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('retval', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('id_progetto', 'retval');
这是返回错误的代码:
DECLARE
id_progetto NUMBER;
retval NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (COD_FIS, MATRICOLA, STATO, STATO_INTERNO, DATA_PRESENTAZIONE, DATA_ULTIMA_MODIFICA)
VALUES (:cod_fis, :matricola, 'A', 'C', TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (ID_PROGETTO, OBIETTIVO)
VALUES (:id_progetto, :obiettivo);
:retval := :id_progetto;
END;
虽然此代码有效:
DECLARE
id_progetto NUMBER;
retval NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (COD_FIS, MATRICOLA, STATO, STATO_INTERNO, DATA_PRESENTAZIONE, DATA_ULTIMA_MODIFICA)
VALUES (:cod_fis, :matricola, 'A', 'C', TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE) RETURNING SUBSTR(id,1,3) INTO :id_progetto; /* here I'm truncating the number to 3 digits */
INSERT INTO LAVORO_TELE_OBIETTIVO (ID_PROGETTO, OBIETTIVO)
VALUES (:id_progetto, :obiettivo);
:retval := :id_progetto;
END;
谢谢, 亚历克斯
ORA-06502 可能是您尝试执行导致算术、数字、字符串、转换或约束错误的语句的结果。
- 您试图为数字变量赋值,但该值大于变量可以处理的值
- 这就是你报告的内容
- 您试图将 non-numeric 值分配给数值变量并导致转换错误
- 这里闻起来不对
如果您设法使用 substr
使其工作,是否有可能 insert
语句返回的值实际上是一个 字符串 (例如 123A
) 不能放入 NUMBER
数据类型变量?
因为,将 4 位数字存储到 non-constrained NUMBER
数据类型变量中没有问题。
SQL> declare
2 l_id_progetto number;
3 begin
4 l_id_progetto := 123456789;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
此外,这就是你正在做的(简化):
DECLARE
id_progetto NUMBER;
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (...)
RETURNING id INTO :id_progetto;
^
|
what is this colon doing here?
不应该吗
returning id into id_progetto
相反?看起来你正在将它插入到......嗯,这个 PL/SQL 程序之外的东西(例如 Oracle Forms 字段,Apex 页面项目,实际上 是 能够仅包含 3 个字符,但 - 不是本地声明的变量)。
您正在混合在 DECLARE
子句中定义的局部 PL/SQL 变量和前缀为 :
的全局定义的绑定变量。尽管它们可能具有相同的标识符,但它们不是同一个变量。
您可能想要的是:
DECLARE
id_progetto NUMBER; -- local variable
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE
) RETURNING id INTO id_progetto; -- into the local variable
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
id_progetto, :obiettivo -- read the local variable
);
:retval := id_progetto; -- out into the global bind variable
END;
可能using:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('retval', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('retval', 'retval');
或者,不使用任何局部变量:
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
TO_DATE(:dataPresentazione, 'YYYY-MM-DD HH24:MI:SS'),
SYSDATE
) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
:id_progetto, :obiettivo
);
END;
然后:
$paramContainer = new ParameterContainer();
$paramContainer->offsetSet('cod_fis', $this->cf_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('matricola', $this->matr_dipendente, $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('dataPresentazione', $validatedData['dataPresentazione'], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('obiettivo', $validatedData["obiettivo"], $paramContainer::TYPE_AUTO);
$paramContainer->offsetSet('id_progetto', '0', $paramContainer::TYPE_STRING);
$paramContainer->offsetSetReference('id_progetto', 'id_progetto');
你也不应该将日期作为字符串传递,而应该只使用 DATE
数据类型(在 Oracle 中,DATE
总是有一个时间部分;这可能意味着 Zend 中的等价物是时间戳数据类型而不是日期)。
如果您确实将其作为 Oracle DATE
传递,那么您的代码将变为:
BEGIN
INSERT INTO LAVORO_TELE_PROGETTO (
COD_FIS,
MATRICOLA,
STATO,
STATO_INTERNO,
DATA_PRESENTAZIONE,
DATA_ULTIMA_MODIFICA
) VALUES (
:cod_fis, :matricola,
'A',
'C',
:dataPresentazione,
SYSDATE
) RETURNING id INTO :id_progetto; /* id is 4 digits long */
INSERT INTO LAVORO_TELE_OBIETTIVO (
ID_PROGETTO, OBIETTIVO
) VALUES (
:id_progetto, :obiettivo
);
END;
并且您不想在 Zend 代码中使用 ::TYPE_AUTO
,而是指定绑定变量的实际类型(如果 Zend 支持 ::TYPE_DATE
或 ::TYPE_TIMESTAMP
,这并不明显它确实如此)。
对于您的 Zend 代码,您要确保您使用的 id_progetto
and/or retval
中的任何一个被声明为 OUT
或 IN/OUT
参数绑定变量而不是 IN
参数。
从 this bug 开始,您似乎需要在同一个绑定参数上同时使用 offsetSet
和 offsetSetReference
(但 Zend/Lamina 文档在描述了这些方法应该做什么,但没有给出明显识别 OUT
或 IN/OUT
绑定变量的实际示例。