Oracle 19.17 引用序列作为主键列的默认值失败,并显示 ORA 02262

Oracle 19.17 Reference a sequence as default of Primary Key column fails with ORA 02262

提问人:Mark R 提问时间:8/24/2023 最后编辑:LittlefootMark R 更新时间:8/25/2023 访问量:58

问:

与现有表和序列一起使用的此命令失败,并显示 ORA 02262 错误:在类型检查列默认表达式时发生错误

MESSAGES TABLE INFO
ID NUMBER(38) Primary Key

ALTER TABLE MESSAGES MODIFY
ID DEFAULT MESSAGES.SEQ.NEXTVAL

但是我可以这样做

CREATE SEQUENCE TEST_SEQ;

CREATE TABLE TEST
(ID NUMBER NOT NULL,
NAME VARCHAR2)

然后

ALTER TABLE TEST MODIFY
(ID DEFAULT TEST_SEQ.NEXTVAL

它会起作用的。

主要目标是摆脱使用序列和触发器的组合来帮助填充 ID,并朝着更接近 IDENTITY 的概念迈进,如此处所述

Oracle 12c:如何将现有主键列修改为标识列?

  1. 我不相信存在类型检查问题,因为序列应该返回一个 NUMERIC 值,该值将进入 NUMERIC 列类型?

  2. 授权应该是可以的,因为使用带有序列和触发器的“旧方式”将数据插入消息表。


ALTER TABLE MESSAGES MODIFY
ID DEFAULT MESSAGES.SEQ.NEXTVAL

但是我可以这样做

CREATE SEQUENCE TEST_SEQ;

CREATE TABLE TEST
(ID NUMBER NOT NULL,
NAME VARCHAR2)

然后

ALTER TABLE TEST MODIFY
(ID DEFAULT TEST_SEQ.NEXTVAL

它会起作用的。

Oracle 序列 标识

评论

0赞 APC 8/25/2023
在你的第一个语句中,你的序列名是无效的(除非你有另一个名为 MESSAGES 的模式,它已将序列 SEQ 的权限授予您的表所有者)所以也许问题只是你尝试使用错误的序列名称。最好的办法是发布 CREATE TABLE 和 CREATE SEQUENCE 命令,然后允许重现 ORA-02622 错误。

答:

3赞 Littlefoot 8/25/2023 #1

对不起,但我不太明白你想说什么。

标题建议您使用 Oracle 19。它支持标识列,所以 - 你为什么不使用该功能呢?请注意,Oracle 会在后台创建一个序列,所以如果你认为你会摆脱一个序列 - 不,你不会。但是您不必使用触发器,这是正确的。

SQL> create table messages (id number generated always as identity primary key);

Table created.

如果你按照自己的方式去做,你为什么认为它应该起作用?

SQL> create table messages (id number primary key);

Table created.

SQL> alter table messages modify id default MESSAGES.SEQ.NEXTVAL;
alter table messages modify id default MESSAGES.SEQ.NEXTVAL
                            *          ====================
ERROR at line 1:                       what does this represent?        
ORA-02262: ORA-2289 occurs while type-checking column default value expression

序列必须存在,然后才能将其用作默认值;我不认为甲骨文会以这种方式为你创建一个:

SQL> create sequence seq;

Sequence created.

SQL> alter table messages modify id default SEQ.NEXTVAL;

Table altered.

SQL>

因此,从我的角度来看,一切都按预期进行。如果我错了,请解释为什么你认为我错了,如果可能的话,请提供不同的文件。

评论

0赞 Mark R 8/25/2023
谢谢。首先,我们的互联网与应用程序/数据库基础设施完全隔离,因此我无法直接复制代码。其次,这是一个现有的生产系统,数据在1TB范围内。它也是一个自 2008 年以来一直存在的旧应用程序,多年来经过升级,在 Oracle 19 上。为了尽量减少对生产的影响,目标是摆脱触发器,仅使用列定义的“DEFAULT”选项来使用序列。因此,ALTER.以下链接还描述了问题 stackoverflow.com/questions/32976743
0赞 Mark R 8/26/2023
添加。。。在我上面的例子中没有说明的是,MESSAGES_SEQ已经存在并且是遗留结构的一部分。
0赞 Littlefoot 8/26/2023
然后是你做错了。如果 - 正如您之前的评论所说 - 序列MESSAGES_SEQ(带下划线)存在,您为什么要更改指定 DEFAULT MESSAGES 的表。序列。NEXTVAL(带点)?如果您使用了 DEFAULT MESSAGES_SEQ.NEXTVAL,一切都会(应该)好起来的。
0赞 Mark R 8/29/2023
是的,我确实打错了字,MESSAGES_SEQ不是MESSAGE_SEQ。 已解决