我有一个名为TABLE_1的表,它有3列
row_id row_name row_descr
1 check1 checks here
2 check2 checks there
这些行是通过前端应用程序创建的。现在假设我从前端删除了带有row_name check2的条目,并使用row_name check3从前端创建了另一个条目,在数据库中我的条目如下。
row_id row_name row_descr
1 check1 checks here
3 check3 checks
现在如果你观察到row_id不是正常的一次性增量,现在我的问题是我正在编写一个insert语句来自动化某些东西,我不知道我应该在row_id列中插入什么。以前我认为它只是新的row_id = old row_id +1。但这不是这种情况。请帮忙
编辑: 目前我正在插入这样的错误:
insert into TABLE1 (row_id, row_name, row_descr
) values ( (select max (row_id) + 1 from TABLE1),'check1','checks here');
row_id不是正常的一次增量。
答案 0 :(得分:2)
永远不要用max(id)+1来计算id,除非你绝对可以排除同时的动作(这几乎从来就不是这种情况)。在oracle(12版之前,请参阅Kumars回答)创建一个序列,然后插入该序列中的值。
create sequence my_sequence;
通过触发器,这意味着你根本不需要关心插入过程中的ID:
CREATE OR REPLACE TRIGGER myTrigger
BEFORE INSERT ON TABLE1 FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL INTO :NEW.row_id FROM DUAL;
END;
/
或直接使用插入
insert into TABLE1 (row_id, row_name, row_descr
) values ( my_sequence.nextval,'check1','checks here');
除了在oracle中使用row_id
作为列名可能会有点混乱,因为伪列rowid
具有特殊含义。
尽管如此:如果您确实需要捕获oracle错误作为删除,可以使用PRAGMA EXCEPTION INIT
通过使用插入过程来执行此操作。它可能看起来像这样:
CREATE OR REPLACE PROCEDURE myInsert( [...] )
IS
value_allready_exists EXCEPTION;
PRAGMA EXCEPTION_INIT ( value_allready_exists, -00001 );
--ORA-00001: unique constraint violated
BEGIN
/*
* Do your Insert here
*/
EXCEPTION
WHEN value_allready_exists THEN
/*
* Do what you think is necessary on your ORA-00001 here
*/
END myInsert;
答案 1 :(得分:1)
Oracle 12c
引入了IDENTITY
列。确切地说,Release 12.1
。在您需要为主键列设置sequence
的情况下,它非常方便。
例如,
SQL> DROP TABLE identity_tab PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE identity_tab (
2 ID NUMBER GENERATED ALWAYS AS IDENTITY,
3 text VARCHAR2(10)
4 );
Table created.
SQL>
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 1;
1 row deleted.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 2;
1 row deleted.
SQL> SELECT * FROM identity_tab;
ID TEXT
---------- ----------
3 Text
4 Text
SQL>
现在让我们看看幕后的内容 -
SQL> SELECT table_name,
2 column_name,
3 generation_type,
4 identity_options
5 FROM all_tab_identity_cols
6 WHERE owner = 'LALIT'
7 /
TABLE_NAME COLUMN_NAME GENERATION IDENTITY_OPTIONS
-------------------- --------------- ---------- --------------------------------------------------
IDENTITY_TAB ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999
999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N
, CACHE_SIZE: 20, ORDER_FLAG: N
SQL>
所以,你去吧。由Oracle隐式创建的sequence
。
不要忘记,您只能使用表sequence
的{{1}}选项摆脱purge
。
答案 2 :(得分:0)
如果您不担心导致错误的值,那么可以通过在插入语句中添加/*+ hint */
来解决该问题。
在此示例中,我们将从另一个表或一个内部查询中进行选择,然后将结果插入到名为TABLE_NAME
的表中,该表对名为IDX_COL_NAME
的列具有唯一约束。
INSERT /*+ ignore_row_on_dupkey_index(TABLE_NAME(IDX_COL_NAME)) */
INTO TABLE_NAME(
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n)
SELECT
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n);
Oracle将超越冗余行。如果您担心知道WHICH行导致了此问题或其他原因,那么这不是一个很好的解决方案。但是,如果您对此不关心,只保留插入的第一个值就可以了,那么这应该可以完成工作。
答案 3 :(得分:0)
您可以使用一个异常构建,该异常构建将在唯一键重复的情况下引发
DECLARE
emp_count number;
BEGIN
select count(*) into emp_count from emp;
if emp_count < 1 then
insert into emp
values(1, 'First', 'CLERK', '7839', SYSDATE, 1200, null, 30);
dbms_output.put_line('Clerk added');
else
dbms_output.put_line('No data added');
end if;
EXCEPTION
when dup_val_on_index then
dbms_output.put_line('Tried to add row with duplicated index');
END;