/*+ BYPASS_UJVC*/ 的使用技巧

在使用implict update table 時,發現其中一個表一定要有唯一約束,否則會報錯!但是oracle可以使用hints:/*+ BYPASS_UJVC*/ 屏蔽掉隊唯一性的檢查。具體測試過程如下:

SQL> CREATE TABLE test_a(
  2  id NUMBER ,
  3  score NUMBER );


Table created.
Elapsed: 00:00:00.10
SQL> 


CREATE TABLE test_b(
  2  id NUMBER);

Table created.

Elapsed: 00:00:00.01
SQL>
SQL> INSERT INTO test_a VALUES(1,100);       
INSERT INTO test_a VALUES(2,200);
1 row created.

Elapsed: 00:00:00.01
SQL>
INSERT INTO test_a VALUES(3,300);
1 row created.

Elapsed: 00:00:00.00
SQL>

1 row created.

Elapsed: 00:00:00.00
SQL> INSERT INTO test_b VALUES(1);

1 row created.

Elapsed: 00:00:00.01
SQL> INSERT INTO test_b VALUES(2);

1 row created.

Elapsed: 00:00:00.00
SQL> INSERT INTO test_b VALUES(3);

1 row created.

Elapsed: 00:00:00.01
SQL> INSERT INTO test_b VALUES(4);

1 row created.

Elapsed: 00:00:00.01
SQL>
SQL> SELECT * FROM test_a ORDER BY 1;
SELECT * FROM test_b ORDER BY 1;
        ID      SCORE
---------- ----------
         1        100
         2        200
         3        300

3 rows selected.

Elapsed: 00:00:00.01
SQL>

        ID
----------
         1
         2
         3
         4

4 rows selected.

Elapsed: 00:00:00.01

 

現在更新a表的字段:(先不考慮SQL的功能,只是測試這種方法)

SQL> UPDATE (
  2     SELECT  a.id,a.score,b.id AS b_id
  3     FROM test_a a,
  4             test_b b
  5     WHERE a.id=b.id
  6     )
  7  SET id=b_id;
SET id=b_id
    *
ERROR at line 7:
ORA-01779: cannot modify a column which maps to a non key-preserved table

 

報錯了,需要對b表加唯一索引。加入hints執行

SQL> UPDATE (
  2     SELECT/*+ BYPASS_UJVC*/  a.id,a.score,b.id AS b_id
  3     FROM test_a a,
  4             test_b b
  5     WHERE a.id=b.id
  6     )
  7  SET id=b_id;

3 rows updated.

Elapsed: 00:00:00.01

 

說明:oracle可以跳過檢查唯一約束。

 

繼續往b表添加一條記錄,使b表的記錄不唯一。

SQL> INSERT INTO test_b VALUES(3);

1 row created.

Elapsed: 00:00:00.00
SQL> COMMIT;

Commit complete.

Elapsed: 00:00:00.00
SQL> SELECT * FROM TEST_B ORDER BY 1;

        ID
----------
         1
         2
         3
         3
         4

5 rows selected.

Elapsed: 00:00:00.00

 

SQL> UPDATE (
  2     SELECT/*+ BYPASS_UJVC*/  a.id,a.score,b.id AS b_id
  3     FROM test_a a,
  4             test_b b
  5     WHERE a.id=b.id
  6     )
  7  SET id=b_id;

4 rows updated.

Elapsed: 00:00:00.01
SQL> SELECT * FROM TEST_A;

        ID      SCORE
---------- ----------
         1        100
         2        200
         3        300

3 rows selected.

Elapsed: 00:00:00.00

 

總結:使用了該hints,oracle就完全放棄了檢查唯一性。因此SQL可以執行通過。

 

但要注意,是否能達到我們希望的目的,例如:下面進行一個有意義的更新,將a表中只要id在b表中出現就更新score,將score加1.

執行SQL如下:

SQL> UPDATE (
  2     SELECT/*+ BYPASS_UJVC*/  a.id,a.score,b.id AS b_id
  3     FROM test_a a,
  4             test_b b
  5     WHERE a.id=b.id
  6     )
  7  SET score=score+1;

4 rows updated.

Elapsed: 00:00:00.00
SQL> SELECT * FROM TEST_A;

        ID      SCORE
---------- ----------
         1        101
         2        201
         3        302

3 rows selected.

Elapsed: 00:00:00.01

 

發現對於id=3的記錄多加了個1。因此並沒有得到我們想要的結果。這種情況應該先對b表的id進行去重。然後再更新。(其實完全也可以換種寫法,呵呵) ,在此就不寫了

 

總結:雖然對於此種應用,oracle跳過了檢查唯一性,但是我們要注意在具體使用時,是否真的就達到了我們的效果!

        要巧用並且活用現在已經有的功能。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章