在ITPUB上看到了一个有意思的bug,Oracle的MERGE语法检查不严格,简单记录一下这个问题。
原贴见:http://www.itpub.net/thread-1313319-1-4.html
测试发现即使在11.2中,这个问题仍然存在:
SQL> SELECT * FROM V$VERSION;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> CREATE TABLE T1
2 (ID NUMBER,
3 NAME VARCHAR2(30));
表已创建。
SQL> CREATE TABLE T2
2 (ID NUMBER,
3 NAME VARCHAR2(30));
表已创建。
SQL> INSERT INTO T1 VALUES (1, 'A');
已创建 1 行。
SQL> INSERT INTO T1 VALUES (2, 'A');
已创建 1 行。
SQL> INSERT INTO T2 VALUES (1, 'B');
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> MERGE INTO T2
2 USING (SELECT ID, NAME FROM T1) T1
3 ON (T1.ID = T2.ID)
4 WHEN MATCHED THEN UPDATE
5 SET T2.NAME = T2.T1.NAME
6 WHEN NOT MATCHED THEN INSERT
7 VALUES (T1.ID, T1.NAME);
2 行已合并。
SQL> SELECT * FROM T2;
ID NAME
---------- ------------------------------
1 A
2 A
在MERGE的UPDATE SET语法中,T2.T1.NAME这种错误的写法也被接收,而T2这个前缀被忽略。这里如果不是T2换成其他任意的字符也不会导致错误:
SQL> MERGE INTO T2
2 USING (SELECT ID, NAME FROM T1) T1
3 ON (T1.ID = T2.ID)
4 WHEN MATCHED THEN UPDATE
5 SET T2.NAME = BDW.T1.NAME
6 WHEN NOT MATCHED THEN INSERT
7 VALUES (T1.ID, T1.NAME);
2 行已合并。
SQL> MERGE INTO T2
2 USING (SELECT ID, NAME FROM T1) T1
3 ON (T1.ID = T2.ID)
4 WHEN MATCHED THEN UPDATE
5 SET T2.NAME = SYS.T1.NAME
6 WHEN NOT MATCHED THEN INSERT
7 VALUES (T1.ID, T1.NAME);
2 行已合并。
显然在SELECT或UPDATE语句中,这样的写法是不能通过语法检查的:
SQL> SELECT T2.T1.NAME
2 FROM T1, T2
3 WHERE T1.ID = T2.ID;
SELECT T2.T1.NAME
*
第 1 行出现错误:
ORA-00904: "T2"."T1"."NAME": 标识符无效
SQL> UPDATE T2
2 SET NAME =
3 (
4 SELECT T2.T1.NAME
5 FROM T1
6 WHERE T1.ID = T2.ID
7 );
SELECT T2.T1.NAME
*
第 4 行出现错误:
ORA-00904: "T2"."T1"."NAME": 标识符无效
越是新特性bug就越多,虽然MERGE语法在9i就出现了,但是相比较还是用的比较少,用的人少了,所经历的各种极端的测试就少,隐藏bug的可能性就更多了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-665076/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/4227/viewspace-665076/