/* 很是困惑,ORACLE為什么要用VARCHAR(1)型,用CHAR(1)難道不好么?從這樣的表結(jié)構(gòu)來(lái)看,DUAL表設(shè)計(jì)的目的就是要盡可能的簡(jiǎn)單,以減少檢索的開(kāi)銷(xiāo)。 還有,DUAL表是建立在SYSTEM表空間的,第一是因?yàn)镈UAL表是SYS這個(gè)用戶建的,本來(lái)默認(rèn)的表空間就是SYSTEM;第二,把這個(gè)可能經(jīng)常被查詢(xún)的表和用戶表分開(kāi)來(lái)存放,對(duì)于系統(tǒng)性能的是有好處的。 有了創(chuàng)建了表、創(chuàng)建了同義詞還是不夠的。DUAL在SYS這個(gè)Schema下面,因此用別的用戶登錄是無(wú)法查詢(xún)這個(gè)表的,因此還需要授權(quán): grant select on SYS.DUAL to PUBLIC with grant option; 將Select 權(quán)限授予公眾。 接下來(lái)看看DUAL表中的數(shù)據(jù),事實(shí)上,DUAL表中的數(shù)據(jù)和ORACLE數(shù)據(jù)庫(kù)環(huán)境有著十分重要的關(guān)系(ORACLE不會(huì)為此癱瘓,但是不少存儲(chǔ)過(guò)程以及一些查詢(xún)將無(wú)法被正確執(zhí)行)。 */
--查詢(xún)行數(shù) --在創(chuàng)建數(shù)據(jù)庫(kù)之后,DUAL表中便已經(jīng)被插入了一條記錄。個(gè)人認(rèn)為:DUMMY字段的值并沒(méi)有什么關(guān)系,重要的是DUAL表中的記錄數(shù) SQL> select count(*) from dual; COUNT(*) ---------- 1
SQL> select * from dual; DUMMY ----- X
--插入數(shù)據(jù),再查詢(xún)記錄,只返回一行記錄 SQL> insert into dual values (''Y''); 1 row created. SQL> commit; Commit complete. SQL> insert into dual values (''X''); 1 row created. SQL> insert into dual values (''Z''); 1 row created. SQL> commit; Commit complete. SQL> select count(*) from dual; COUNT(*) ---------- 4 SQL> select * from dual; DUMMY ----- X
/* --假我們插入一條數(shù)據(jù),DUAL表不是返回一行,而是多行記錄,那會(huì)是什么結(jié)果呢? SQL> insert into dual values(''Y''); 1 行 已插入 SQL> commit; 提交完成 SQL> select * from dual; DUMMY ----- X Y SQL> select sysdate from dual; SYSDATE ----------- 2004-12-15 2004-12-15
這個(gè)時(shí)候返回的是兩條記錄,這樣同樣會(huì)引起問(wèn)題。在通過(guò)使用 select sysdate into v_sysdate from dual; 來(lái)獲取時(shí)間或者其他信息的存儲(chǔ)過(guò)程來(lái)說(shuō),ORACLE會(huì)拋出TOO_MANY_ROWS(ORA-01422)異常。 因此,需要保證在DUAL表內(nèi)有且僅有一條記錄。當(dāng)然,也不能把DUAL表的UPDATE,INSERT,DELETE權(quán)限隨意釋放出去,這樣對(duì)于系統(tǒng)是很危險(xiǎn)的 */
--把表截掉 SQL> truncate table dual; Table truncated. SQL> select count(*) from dual; COUNT(*) ---------- 0 SQL> select * from dual; no rows selected SQL> select sysdate from dual; no rows selected
--試著把DUAL表中的數(shù)據(jù)刪除,看看會(huì)出現(xiàn)什么結(jié)果: SQL> delete from dual; 1 行 已刪除 SQL> select * from dual; DUMMY ----- SQL> select sysdate from dual; SYSDATE ----------- /* 我們便取不到系統(tǒng)日期了。因?yàn)?#xff0c;sysdate是個(gè)函數(shù),作用于每一個(gè)數(shù)據(jù)行?,F(xiàn)在沒(méi)有數(shù)據(jù)了,自然就不可能取出系統(tǒng)日期。 這個(gè)對(duì)于很多用 select sysdate into v_sysdate from dual; 這種方式取系統(tǒng)時(shí)間以及其他信息的存儲(chǔ)過(guò)程來(lái)說(shuō)是致命的,因?yàn)?#xff0c;ORACLE會(huì)馬上拋出一個(gè)NO_DATA_FOUND(ORA-01403)的異常,即使異常被捕獲,存儲(chǔ)過(guò)程也將無(wú)法正確完成要求的動(dòng)作。 */
--對(duì)于DELETE操作來(lái)說(shuō),ORACLE對(duì)DUAL表的操作做了一些內(nèi)部處理,盡量保證DUAL表中只返回一條記錄.當(dāng)然這寫(xiě)內(nèi)部操作是不可見(jiàn)的 --不管表內(nèi)有多少記錄(沒(méi)有記錄除外),ORACLE對(duì)于每次DELETE操作都只刪除了一條數(shù)據(jù)。 SQL> select count(*) from dual; COUNT(*) ---------- 2 SQL> delete from dual; 1 行 已刪除 SQL> commit; 提交完成 SQL> select count(*) from dual; COUNT(*) ---------- 1
/* 附: ORACLE關(guān)于DUAL表不同尋常特性的解釋 There is internalized code that makes this happen. Code checks that ensurethat a table scan of SYS.DUAL only returns one row. Svrmgrl behaviour is incorrect but this is now an obsolete product. The base issue you should always remember and keep is: DUAL table should always have 1 ROW. Dual is a normal table with one dummy column of varchar2(1). This is basically used from several applications as a pseudo table for getting results from a select statement that use functions like sysdate or other prebuilt or application functions. If DUAL has no rows at all some applications (that use DUAL) may fail with NO_DATA_FOUND exception. If DUAL has more than 1 row then applications (that use DUAL) may fail with TOO_MANY_ROWS exception. So DUAL should ALWAYS have 1 and only 1 row */
DUAL表可以執(zhí)行插入、更新、刪除操作,還可以執(zhí)行drop操作。但是不要去執(zhí)行drop表的操作,否則會(huì)使系統(tǒng)不能用,數(shù)據(jù)庫(kù)起不了,會(huì)報(bào)Database startup crashes with ORA-1092錯(cuò)誤。
3、如果DUAL表被“不幸”刪除后的恢復(fù): 用sys用戶登陸。 創(chuàng)建DUAL表。 授予公眾SELECT權(quán)限(SQL如上述,但不要給UPDATE,INSERT,DELETE權(quán)限)。 向DUAL表插入一條記錄(僅此一條): insert into dual values(''X''); 提交修改。 --用sys用戶登陸。 SQL> create pfile=’d:/pfile.bak’ from spfile SQL> shutdown immediate --在d:/pfile.bak文件中最后加入一條:replication_dependency_tracking = FALSE --重新啟動(dòng)數(shù)據(jù)庫(kù): SQL> startup pfile=’d:/pfile.bak’ SQL> create table “sys”.”DUAL” ( “DUMMY” varchar2(1) ) pctfree 10 pctused 4; SQL> insert into dual values(‘X’); SQL> commit; SQL> Grant select on dual to Public; 授權(quán)成功。