今天中山公司讓遠程看下調度安排批次老是報單據已經安排批次的錯誤,由於是一樣的源程序,作正式庫就不報錯,作測試庫就報錯了,想到的是數據的問題或者是數據庫設置的問題,因而就對源程序進行調試,程序在走到datawindow的of_update()的時候報錯,這個很明顯,應該是更新sql報的錯,因而把datawindow的sql語句拿出來,根據安排批次的業務過程,最終抽取爲一句sql語句:UPDATE VIW_CK_BCARR SET ZUOY_STATE='D1',BOCI_NO='00000012' WHERE DANJ_NO ='XXXXXX';既然從pb走是報錯的,所需拿出來在plsql裏面跑了一把,發現報「ORA-01779: 沒法修改與非鍵值保存表對應的列」,明顯是後臺的錯誤,本身想應該是和表鍵有關,因而看和VIW_CK_BCARR試圖相關聯的8個表,發現這八個表都沒主鍵,可見是剛創建的庫,而且創建有問題,對照正式庫把每一個表的主鍵加上後,再執行該語句成功,再前臺執行批次安排,也沒報錯,問題解決!html
對數據庫檢查沒有主鍵的表檢查,請參看http://blog.sina.com.cn/s/blog_b43f755b0101gkyb.htmlsql
可是,這個問題也讓我對viwe的更新有了新的認識,以前只對單表的viwe進行更新,此次對viwe作個全面的總結,避免下次有同事出現相似的問題,一下能夠把更新的sql語句看作試圖看待,實際機制是同樣的。
表test1數據庫
create table test1 ( id number, gender varchar2(10) ); insert into test1 values(1,'男'); insert into test1 values(2,'女'); insert into test1 values(3,'女'); insert into test1 values(4,'女');
表test2oracle
create table test2 ( id number, gender varchar2(10) ); insert into test2 values(2,'男'); insert into test2 values(3,'男'); insert into test2 values(5,'女');
如今狀況以下,test1與test2中ID相同的,我想用test2中的gender更新test1中的gender,使用下列語句
測試
UPDATE ( SELECT A.ID AI,A.GENDER AG,B.ID BI,B.GENDER BG FROM TEST1 A,TEST2 B WHERE A.ID = B.ID ) SET AG = BG; ERROR AT LINE 6: ORA-01779: CANNOT MODIFY A COLUMN WHICH MAPS TO A NON KEY-PRESERVED TABLE
這個錯誤產生的緣由是子查詢的結果中,用來更新test1的test2表id不惟一,致使被更新對象test1中的一行可能要對應test2中的不少行,這樣oracle就不知道該怎麼更新spa
解決辦法
1.給test2加上一個主鍵.調試
SQL> ALTER TABLE TEST2 ADD PRIMARY KEY(ID); TABLE ALTERED. SQL> UPDATE ( SELECT A.ID AI,A.GENDER AG,B.ID BI,B.GENDER BG FROM TEST1 A,TEST2 B WHERE A.ID = B.ID )SET AG = BG; 2 ROWS UPDATED.
SQL>SELECT * FROM TEST1;code
--------------htm
1 男
2 男
3 男
4 女對象
SQL> ALTER TABLE TEST2 DROP PRIMARY KEY; TABLE ALTERED.
2.給test2加上一個惟一索引
SQL> CREATE UNIQUE INDEX IDX_TEST2 ON TEST2(ID); INDEX CREATED. SQL> UPDATE ( SELECT A.ID AI,A.GENDER AG,B.ID BI,B.GENDER BG FROM TEST1 A,TEST2 B WHERE A.ID = B.ID ) SET AG = BG; 2 ROWS UPDATED. SQL> DROP INDEX IDX_TEST2; INDEX DROPPED.
3.使用BYPASS_UJVC強制執行,BYPASS_UJVC能夠跳過ORACLE的鍵檢查.
SQL> UPDATE ( SELECT A.ID AI,A.GENDER AG,B.ID BI,B.GENDER BG FROM TEST1 A,TEST2 B WHERE A.ID = B.ID )SET AG = BG; 2 rows updated.
雖然這樣能夠執行,可是test2中存在不惟一的數據,因此test1可能被更新屢次.
【補充提示】:假如用table2來更新table1,那麼必須保證table2中的結果具備惟一性。好比能夠給table2加上主鍵。若是table2的主鍵有兩個,那麼在更新的時候,必須將table2的主鍵都用來關聯對應table1中的表。(加惟一索引也是這個道理)。