目标(举例子说明): 创建表 CREATE TABLE INC_TEST( ID NUMBER(6), NAME VARCHAR2(125) );
希望在插入新的数据且没有提供 id 值时,会将 id 值设置为一个在表的数据中没有用过的值;而插入新的数据时如果有提供 id 值,则使用所提供的 id 值。
例如执行 1) INSERT INTO INC_TEST(NAME) VALUES('nobdy');时,假如表内数据为空,则会加入一条数据为:(ID: 1, NAME: nobdy)然后再执行 2) INSERT INTO INC_TEST(NAME) VALUES('admin');后,则会增加一条数据:(ID: 2, NAME: admin)接着再执行 3) INSERT INTO INC_TEST(ID, NAME) VALUES(10, 'test');后,则会增加数据:(ID: 10, NAME: test)最后执行 4) INSERT INTO INC_TEST(NAME) VALUES('coremail');后,增加一条数据为:(ID: 11, NAME: coremail)
在 google 搜索了一下,发现网上所提供的方法都大同小异,即在插入数据时也不管用户有没有提供值就将其设置为自增的值,这样用户设置的值就丢失了。比如在执行上面例子中的 3) 时,插入的数据变成了(ID: 3, NAME: test)。
经过一番尝试,发现用一个 sequence 和一个 trigger 可以解决这个问题, 所有的代码如下所示:DROP TABLE INC_TEST;CREATE TABLE INC_TEST( ID NUMBER(6), NAME VARCHAR2(125));DROP SEQUENCE INC_TEST_SEQ;CREATE SEQUENCE INC_TEST_SEQ INCREMENT BY 1 START WITH 1 ORDER;CREATE OR REPLACE TRIGGER INC_INC_TESTBEFORE INSERT ON INC_TESTFOR EACH ROWDECLARE CURRENT_VAL NUMBER:=0;BEGIN IF :NEW.ID IS NULL THEN SELECT INC_TEST_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL; ELSE LOOP EXIT WHEN (CURRENT_VAL >= :NEW.ID); SELECT INC_TEST_SEQ.NEXTVAL INTO CURRENT_VAL FROM DUAL; END LOOP; END IF;END;/INSERT INTO INC_TEST(NAME) VALUES('nobdy');INSERT INTO INC_TEST(NAME) VALUES('admin');INSERT INTO INC_TEST(ID, NAME) VALUES(10, 'test');INSERT INTO INC_TEST(NAME) VALUES('coremail');INSERT INTO INC_TEST(ID, NAME) VALUES(5, 'mailtech');INSERT INTO INC_TEST(NAME) VALUES('simon');