Table 名字和 Schema名字相同:
有schema和表名都為Arwen.
Schema Arwen裡面有一個包PKG,包裡有函數Plus,返回兩數相加的結果
SELECT Arwen.PKG.Plus(1,2) FROM dual; --執行這條sql沒出啥錯,返回結果3.
但在一個pl/sql 塊中就出錯了
declare
result int;
begin
select Arwen.PKG.Plus(1,2) into result from dual;
dbms_output.put_line(result);
end;
如果把表Arwen Drop掉,則pl/sql塊正確執行.(如果有函數或視圖等其他對象的名字和schema相同也會出錯)
關於這問題的解釋
覺得有點奇怪就上網搜了下,然後在Oralce官方網站上看到有關pl/sql的名字解析方式的介紹,有這麼一段話:
PL/SQL and SQL resolve qualified names differently.
For example, when resolving the table name HR.JOBS:
• PL/SQL searches first for packages, types, tables, and views named HR in the current schema, and then for objects named JOBS in the HR schema.
• SQL searches first for objects named JOBS in the HR schema, and then for packages, types, tables, and views named HR in the current schema.
按這解釋貌似就可以理解上面的問題了.在sql的名字解析中,碰到帶點號的這樣的首碼先是把點號前面的當Schema解析,那麼Arwen.PKG.Plus(1,2)這語句是先把Arwen當
Schema,然後PKG解析成Schema下的對象,在這裡是包.但在PL/SQL中先把點後前面的當成當前schema下的對象,這樣Arwen.PKG.Plus(1,2)中的Arwen先被解析成表Arwen,然後pkg解析成表中欄位,由於沒這樣的欄位就出錯了
看起來Oracle文檔上說的沒錯了,不過發現再弄個例子一試,還是有問題啊,文檔裡說HR.JOBS是個表,是表的話不太好舉例,我就把JOBS改成個函數吧.樣本如下
有Schema HR,HR中
有函數JOBS,(沒有參數,返回字串'jobs of schema').
有包HR,包中有函數JOBS,(沒有參數,返回字串'jobs of pkg').
如果按照文檔裡說的,SELECT HR.JOBS FROM dual;--應該返回的是jobs of schema.
而在pl/sql塊中
declare
v_txt varchar2(100);
begin
SELECT HR.JOBS into v_txt FROM dual;
dbms_output.put_line(v_txt);--列印的應該是jobs of pkg
end;
但實際結果不管在sql中還是pl/sql中都是jobs of pkg.
難道Oracle官方文檔裡說的是坑爹的啊?
哎不管它坑不坑爹,平時盡量注意別把對象名和schema名搞成一樣,不然到時出問題了還不容易知道哪出錯了,
我其實也不是喜歡鑽文法的牛角尖來研究這問題,只是在工作中確實碰到了這問題,犯暈了好久才找到這蛋痛的原因啊.
我碰到這問題是這樣一種情境下,我是使用FGA這功能,建立了些審計策略來記錄所有schema的DML操作.審計策略中有調用到一個包中的函數,調用時包名前加了schema做首碼.這個首碼是必須得加的.因為在其他schema中做DML操作觸發審計策略調用那函數時沒schema首碼會找不到的。結果由於那些審計策略所在的schema中有個表名和schema名字相同,結果悲劇就出現了.所有schema做DML操作時觸發了審計策略,然後又調用那函數,但調用時出錯.這意味著所有schema的DML操作都不能完成了,也意味著差不多整個資料庫算是沒法用了,想一想這麼嚴重的影響就流汗了,如果要是生產環境中被我這樣一整,我估計會被罵死了啊........
編輯精選:Oracle時間類型date,timestamp時間差計算
更多Oracle相關資訊見Oracle 專題頁面 http://www.bkjia.com/topicnews.aspx?tid=12