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 字段将被分配下一个数字 供应商序列。供应商名称字段将设置为 卡夫食品。
你说:
我的印象是这会自动找到最高的
USERS
的USER_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,自动编号不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
ALTER SESSION SET nls_date_format 在 APEX 中不起作用。但是在 SQL Developer 中工作