Oracle欄位的預設值無效的原因
阿新 • • 發佈:2019-02-13
幾天前有人問我設定了欄位的預設值為什麼無效,查找了一些資料,總結如下:
create table TEST(IDVARCHAR2(64),AVARCHAR2(3)default'0',NAMEVARCHAR2(100));
SQL>insert into test(a,name) values(null,'test');
1 row inserted
SQL>select * from test;
A NAME
先看第一種方式,
SQL>insert into test(a,name)values(default,'test');
1 row inserted
SQL>select * from test;
A NAME
0 test
SQL>insert into test2(name) values('test');
1 row inserted
SQL>select * from test2;
A NAME
0 test
可以將下面的系統屬性作為預設值:
SYSDATE:系統時間
SYS_CONTEXT:系統上下文
USER:當前資料庫使用者
USERENV:使用者環境變數,可以獲取一些IP地址、協議、終端的資訊
需要注意,預設值不能使用LEVEL、PRIOR、ROWNUM,會報ORA-00976錯誤。
應用中使用預設值的常見場景是主鍵或自增列。正如我們所知,Oracle並未提供自增型別,這就需要我們結合預設值進行二次開發,通過預設值實現系統應用的透明。這裡結合筆者的經驗,提供兩種方案:
觸發器+序列
因為Oracle不支援在default中使用序列,因此我們只能使用觸發器來實現。
create table TEST(IDVARCHAR2(64),AVARCHAR2(3)default'0', NAMEVARCHAR2(100));
create sequence seq_test;
create orreplace trigger tri_test
before insert on test for eachrow
begin
if:new.idisnullthen
select seq_test.nextvalinto:new.idfromdual;
endif;
end;
/
這種方式適用於對於ID不要求連續性的場景。
Sys_guid()。這個函式返回32位長的資料庫全域性唯一標識。我們可以使用這個函式作為預設值。
alter table TESTmodifyIDdefaultsys_guid()
SQL>insert into test2(name) values('張三');
1 row inserted
SQL>select * from test2;
ID ANAME
7CDB1AF556F6474FABA74FA7A60F08220 張三
這種方式適用於ID不要求有含義,以及併發性較高的場景。
create table TEST(IDVARCHAR2(64),AVARCHAR2(3)default'0',NAMEVARCHAR2(100));
SQL>insert into test(a,name) values(null,'test');
1 row inserted
SQL>select * from test;
A NAME
test
在上面的例子中,雖然A列設定了預設值為0,但插入空仍然無效。其實對於預設值,Oracle支援兩種方式:Default關鍵字,不指定列先看第一種方式,
SQL>insert into test(a,name)values(default,'test');
1 row inserted
SQL>select * from test;
A NAME
0 test
列A終於有了預設值0。
再看第二種方式,SQL>insert into test2(name) values('test');
1 row inserted
SQL>select * from test2;
A NAME
0 test
列A也被新增的預設值。
Oracle的預設值處理要當心,如果應用中使用的是ORM工具,則必須要考慮對於欄位為Null的處理,必要時在ORM工具中將Null轉換為default或插入時去掉值為Null的欄位。可以將下面的系統屬性作為預設值:
SYSDATE:系統時間
SYS_CONTEXT:系統上下文
USER:當前資料庫使用者
USERENV:使用者環境變數,可以獲取一些IP地址、協議、終端的資訊
需要注意,預設值不能使用LEVEL、PRIOR、ROWNUM,會報ORA-00976錯誤。
應用中使用預設值的常見場景是主鍵或自增列。正如我們所知,Oracle並未提供自增型別,這就需要我們結合預設值進行二次開發,通過預設值實現系統應用的透明。這裡結合筆者的經驗,提供兩種方案:
觸發器+序列
因為Oracle不支援在default中使用序列,因此我們只能使用觸發器來實現。
create table TEST(IDVARCHAR2(64),AVARCHAR2(3)default'0',
create sequence seq_test;
create orreplace trigger tri_test
before insert on test for eachrow
begin
if:new.idisnullthen
select seq_test.nextvalinto:new.idfromdual;
endif;
end;
/
這種方式適用於對於ID不要求連續性的場景。
Sys_guid()。這個函式返回32位長的資料庫全域性唯一標識。我們可以使用這個函式作為預設值。
alter table TESTmodifyIDdefaultsys_guid()
SQL>insert into test2(name) values('張三');
1 row inserted
SQL>select * from test2;
ID ANAME
7CDB1AF556F6474FABA74FA7A60F08220 張三
這種方式適用於ID不要求有含義,以及併發性較高的場景。