我有一个脚本,我希望有一个全局变量来存储一个事务编号供以后使用。代码在一个模式上正常工作,其中我获取的序列值相对较低。它没有在具有更高序列值的另一个模式上工作,我得到“数字溢出”。如果我将序列值更改为较低的数字,它也可以正常工作,但这不是一个选项。
VAR TRANSACTIONNR NUMBER;
BEGIN
--Works with NEXTVAL being around 946713241
--Doesn't work with NEXTVAL being around 2961725541
SELECT MY_SEQUENCE.NEXTVAL INTO :TRANSACTIONNR FROM DUAL;
MY_PACKAGE.STARTTRANSACTION(:TRANSACTIONNR);
END;
/
-- SQL Statements
BEGIN
MY_PACKAGE.ENDTRANSACTION;
MY_PACKAGE.DO_SOMETHING(:TRANSACTIONNR);
END;
/
还有效的是将序列选择到DECLARE块中声明的变量中:
DECLARE
TRANSACTIONNR NUMBER;
BEGIN
SELECT MY_SEQUENCE.NEXTVAL INTO TRANSACTIONNR FROM DUAL;
MY_PACKAGE.STARTTRANSACTION(TRANSACTIONNR);
END;
/
但这意味着我最终无法在块中重复使用它。无法设置数字的大小。
VAR TRANSACTIONNR NUMBER(15)
无效。
我可以尝试的任何想法或其他存储全球状态的方法吗?
答案 0 :(得分:1)
在进一步调查中,这看起来似乎可能是一个SQL Developer错误(当然还要假设你正在做什么......)。我可以得到同样的错误:
VAR TRANSACTIONNR NUMBER;
BEGIN
SELECT 2961725541 INTO :TRANSACTIONNR FROM DUAL;
END;
/
似乎SQL Developer NUMBER
仅限于2^31
,而Oracle通常不会这样。
一个可能的解决方法是使用BINARY_FLOAT
来存储值,但最终会遇到精度问题(不确定在哪里,但看起来好到2^53
- ish),而你'在使用它时,我需要cast()
返回NUMBER
。
VAR TRANSACTIONNR BINARY_DOUBLE;
BEGIN
SELECT 2961725541 INTO :TRANSACTIONNR FROM DUAL;
-- dbms_output.put_line(cast(:TRANSACTIONNR as NUMBER)); -- null for some reason
END;
/
...
BEGIN
dbms_output.put_line(cast(:TRANSACTIONNR as NUMBER));
END;
/
出于某种原因,我似乎无法在我设置的匿名块中再次引用绑定变量 - 它在注释掉的代码中为空 - 这似乎是另一个SQL Developer怪癖,无论是什么var
类型;但正如你在代码中所做的那样,我可能会再次假设太多......
后代的原始答案,因为它在其他情况下可能仍然有用......
据推测,你正在做一些事情以结束当前的交易,例如commit
中的endtransaction
;否则,您可以在my_sequence.currval
来电中引用do_something
。 number
变量对于这个数量的大小是好的,但它对于大小的序列没有问题,并且它不会与序列而不是手动分配有任何区别。我认为问题不在于存储或序列。
似乎更有可能的是,错误来自您正在调用的一个程序包,尽管我无法想象您可能正在使用它做什么;这样的事情会导致同样的错误:
create sequence my_sequence start with 2961725541;
create package my_package as
procedure starttransaction(v_num number);
procedure endtransaction;
procedure do_something(v_num number);
end my_package;
/
create package body my_package as
procedure starttransaction(v_num number) is
begin
dbms_output.put_line('starttransaction(): ' || v_num);
for i in 1..v_num loop
null;
end loop;
end starttransaction;
procedure endtransaction is
begin
dbms_output.put_line('endtransaction()');
end endtransaction;
procedure do_something(v_num number) is
begin
dbms_output.put_line('do_something(): ' || v_num);
end do_something;
end my_package;
/
当你的代码运行时,它会抛出你的错误:
BEGIN
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at "STACKOVERFLOW.MY_PACKAGE", line 6
ORA-06512: at line 5
endtransaction()
do_something():
请注意,错误是针对包中的第6行报告的,这是for ... loop
行,而不是来自匿名块中的赋值。
nextval
高于2^31
,则其工作的断点。如果我使用2147483647启动序列,则可以使用2147483648错误。
我假设你实际上从原始问题中得到ORA-01426
;如果它实际上是ORA-1438
或ORA-06502
,那么通过尝试将值分配给number(9)
列或变量,可以更容易地重现。 “数字溢出”非常具体。