Oracle APEX,自动编号不起作用?

Posted

技术标签:

【中文标题】Oracle APEX,自动编号不起作用?【英文标题】:Oracle APEX, autonumber not working? 【发布时间】:2012-09-28 05:48:32 【问题描述】:

我是 Oracle 的新手,也是 Oracle Application Express 的新手。

我正在阅读手册,我正在尝试创建一个包含 3 个字段的表格:

USER_ID:编号、主键、自动编号

USER_NAME:VARCHAR2,唯一

密码:VARCHAR2

我使用 APEX SQL Workshop 向导创建表,但是当我尝试执行以下操作时:

INSERT INTO Schema.USERS (USER_NAME,PASSWORD) VALUES ('planet','password');

...我被告知违反了对主键的唯一约束。

表创建向导自动创建了一个触发器。它看起来像这样:

create or replace trigger "BI_USERS" 
  before insert on "USERS"               
  for each row  
begin   
  if :NEW."USER_ID" is null then
    select "USERS_SEQ".nextval into :NEW."USER_ID" from sys.dual;
  end if;
end; 

我的印象是,这会自动找到 USERS 的 USER_ID 字段中的最高数值,并自动为每个新 INSERT 分配一个递增的值,但这似乎没有发生。

谁能建议我做错了什么?

非常感谢

【问题讨论】:

【参考方案1】:

序列:http://www.techonthenet.com/oracle/sequences.php

(引用自链接文章) 在 Oracle 中,您可以使用序列创建自动编号字段。一种 sequence 是Oracle中用于生成数字的对象 顺序。当您需要创建唯一编号时,这可能很有用 充当主键。

...

此插入语句将向供应商插入一条新记录 桌子。供应商 ID 字段将被分配下一个数字 供应商序列。供应商名称字段将设置为 卡夫食品。

你说:

我的印象是这会自动找到最高的 USERSUSER_ID 字段中的数值并自动 为每个新的 INSERT 分配一个递增的值,但这不会 似乎正在发生。

没有。序列将根据最后一个值和增量简单地生成下一个值,并且与您的数据无关。

select nvl(max(user_id), 0) + 1 
  into v_next_val 
  from users 

会查看您的数据并将最高的USER_ID 增加到1

如果您现在由于USER_ID 上的主键而违反约束,这可能意味着您已将数据插入到用户表中,并且该数据包含USER_ID 列的值。 例如,假设创建了 3 条记录并手动将值分配给 USER_ID,而不使用序列

insert into users (user_id, user_name) values (1, 'John');
insert into users (user_id, user_name) values (2, 'Jerry');
insert into users (user_id, user_name) values (3, 'Bob');

当您随后开始使用该序列(或仅在那时创建它)时,该序列将从 value = 1 的指定起点开始。 就这样吧

insert into users (user_name) values ('planet');

会产生约束冲突,因为 sequence.nextval 将为 1。

【讨论】:

谢谢汤姆,非常感谢您的回答!点【参考方案2】:

正如@Tom 所说,如果您在表中插入了为 USER_ID 指定值的行,则该序列的使用被绕过,您现在可能在表中的行中包含 USER_ID 值的重复值,这些值将从序列;因此,在插入新行时,您会收到 PRIMARY KEY CONSTRAINT VIOLATION 错误。要解决此问题,请编写一个小脚本,该脚本“使用”序列中的值并丢弃它们,如下所示:

DECLARE
  n       NUMBER := 122;  -- or however many sequence values you need to consume
  seqVal  NUMBER;
BEGIN
  FOR i IN 1..n LOOP
    SELECT USERS_SEQ.NEXTVAL INTO seqVal FROM DUAL;
  END LOOP;
END;

另一种选择是删除序列并重新创建它,其最小值大于 USERS.USER_ID 的最大值。

分享和享受。

【讨论】:

或者,正如 techonthenet 文章所述:将增量设置为 121,执行一次 nextval,并将增量重置为 1。此外,如果您重新创建序列,我不一定会触及最小值,而是以价值开头。 谢谢 Bob,希望我可以将多个帖子标记为答案——我什至还没有达到点赞帖子的门槛。但是,我仍然感谢您的意见!点【参考方案3】:

这可能会有所帮助:

create or replace TRIGGER  "TR_USER"
before insert on "USER"
for each row
begin   
   if :NEW."IDUSER" is null then
     select max("IDUSER")+1 into :NEW."IDUSER" from USER;
  end if;
end;

【讨论】:

永远不要使用 max(id)+1 来填充序列。这将在多用户环境中失败。

以上是关于Oracle APEX,自动编号不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

入门链接在 oracle 11g 服务器中不起作用

入门链接在oracle 11g服务器中不起作用

案例条件在 apex 日历和 sql 开发人员中不起作用

ALTER SESSION SET nls_date_format 在 APEX 中不起作用。但是在 SQL Developer 中工作

Apex Oracle - 多个动态操作

Oracle apex 从集合中下载 blob 文件