加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Oracle 10:INSERT进入视图时难以理解的行为?

发布时间:2020-12-12 12:57:17 所属栏目:百科 来源:网络整理
导读:我们这里有一个奇怪的问题,我们无法向自己解释. 我们在Oracle DB Version 10.2.0.5.8中有一个视图.该视图使用INSTEAD OF触发器. 这是触发器的代码: CREATE OR REPLACE TRIGGER V1_T1_BIUD INSTEAD OF INSERT OR UPDATE OR DELETE ON V1_T1 FOR EACH ROWDECL
我们这里有一个奇怪的问题,我们无法向自己解释.

我们在Oracle DB Version 10.2.0.5.8中有一个视图.该视图使用INSTEAD OF触发器.

这是触发器的代码:

CREATE OR REPLACE TRIGGER V1_T1_BIUD
  INSTEAD OF INSERT OR UPDATE OR DELETE
  ON V1_T1
  FOR EACH ROW
DECLARE
  AnyId   NUMBER;
BEGIN
  IF INSERTING THEN
    INSERT INTO Table T1 (
       F1,F2,F3,F4,F5
    ) VALUES (
       :new.F1,:new.F2,:new.F3,:new.F4,:new.F5
    );
  ELSIF UPDATING THEN
    UPDATE T1 SET F1 = :new.F1,F2 = :new.F2,F3 = :new.F3,F4 = :new.F4,F5 = :new.F5
    WHERE F1 = :old.F1;
  ELSIF DELETING THEN
    DELETE FROM T1
    WHERE F1 = :old.F1;
  END IF;
END;
/

这是一个INSERT语句示例:

INSERT INTO V_T1 (
  F1,F5
)
SELECT A.V,A.S,A.F,A.T,A.Z
FROM (
  SELECT 'E' V,'N' S,'ABC' F,'E' T,'E' Z FROM DUAL UNION ALL 
  SELECT 'E','Y','QWE','O','E'   FROM DUAL UNION ALL
  SELECT 'I','GHJ','I','I'   FROM DUAL           
) A
ORDER BY 1,2,3;
COMMIT;

注意select的末尾的ORDER BY子句.这个INSERT语句的结果是这样的:

F1 F2 F3  F4 F5
---------------
E  N  ABC I  I 
E  Y  QWE I  I 
I  Y  GHJ I  I

如您所见,第4列和第5列未正确填充所有其他数据行中最后一个数据行的值.

如果我们像这样更改INSERT语句:

INSERT INTO V_T1 (
  F1,3,4,5;
COMMIT;

结果是这样的:

F1 F2 F3  F4 F5
---------------
E  N  ABC E  E 
E  Y  QWE O  E 
I  Y  GHJ I  I

再次,请注意ORDER BY子句,它现在命令所有行而不是第一个insert语句中的前三行.

编辑:如果省略ORDER BY子句,结果也符合预期(例如,如示例2所示).

有人可以向我解释这种行为吗?

P. S.关于评论:

我今天没有时间调查或提供有关此主题的更多信息.我将在我们的数据库上创建一个完整的示例,并在接下来的几天内将其发布到此处.感谢您的耐心等待!

解决方法

这看起来像一个错误,但我找不到bug数据库中的明显匹配(一些看起来可能,如5842445,但是模糊或不完全排队).我只能用触发器来实现它(所以我假设你的插入对T1而不是V1_T1是转录错误);并且只有当F4和F5是CHAR而不是VARCHAR2时:

create table t1 (f1 varchar2(2),f2 varchar2(2),f3 varchar2(3),f4 char(2),f5 char(2));

create view v1_t1 as select * from t1;

…而不是完全如问题所示的触发器.

根据DBMS_OUTPUT,触发器内部的新值是错误的,但是受列数据类型影响的是Oracle认为只能找到的东西.

它仍然发生在11.2.0.3(Linux)中.有趣的是,如果我将UNION ALL更改为UNION,我会得到略微不同的结果;在10g中,两列最终为null,在11g中它们有x:

insert into v1_t1 (
  F1,A.Z
FROM (
    SELECT 'E' V,'E' Z FROM DUAL UNION
    SELECT 'E','E'   FROM DUAL UNION
    SELECT 'I','I'   FROM DUAL
) A
ORDER BY 1,3;

3 rows created.

select * from v1_t1;

F1 F2 F3  F4 F5
-- -- --- -- --
E  N  ABC x  x
E  Y  QWE x  x
I  Y  GHJ x  x

…这甚至更奇怪 – 看起来可能修复了其他一些bug对这个有点影响.

所以不是一个真正的答案;您需要向Oracle发出服务请求,我相当确定他们只是告诉您删除订单,因为它没有任何价值,正如您已经知道的那样.

对于Thilo;没有任何订单的计划(11g):

----------------------------------------------------------------------------------
| Id  | Operation                | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |       |     3 |    51 |     9  (34)| 00:00:01 |
|   1 |  LOAD TABLE CONVENTIONAL | V1_T1 |       |       |            |          |
|   2 |   VIEW                   |       |     3 |    51 |     9  (34)| 00:00:01 |
|   3 |    SORT UNIQUE           |       |     3 |       |     9  (78)| 00:00:01 |
|   4 |     UNION-ALL            |       |       |       |            |          |
|   5 |      FAST DUAL           |       |     1 |       |     2   (0)| 00:00:01 |
|   6 |      FAST DUAL           |       |     1 |       |     2   (0)| 00:00:01 |
|   7 |      FAST DUAL           |       |     1 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------

并按顺序计划1,3或1,5 – 相同的计划哈希值(11g):

----------------------------------------------------------------------------------
| Id  | Operation                | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |       |     3 |    51 |    10  (40)| 00:00:01 |
|   1 |  LOAD TABLE CONVENTIONAL | V1_T1 |       |       |            |          |
|   2 |   SORT ORDER BY          |       |     3 |    51 |    10  (40)| 00:00:01 |
|   3 |    VIEW                  |       |     3 |    51 |     9  (34)| 00:00:01 |
|   4 |     SORT UNIQUE          |       |     3 |       |     9  (78)| 00:00:01 |
|   5 |      UNION-ALL           |       |       |       |            |          |
|   6 |       FAST DUAL          |       |     1 |       |     2   (0)| 00:00:01 |
|   7 |       FAST DUAL          |       |     1 |       |     2   (0)| 00:00:01 |
|   8 |       FAST DUAL          |       |     1 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------

我看到从其他表中选择相同类型的损坏,但前提是子查询中的结果在被排序之前已经联合;虽然然后我得到空值而不是x. (我简单地想知道x是否来自双自身,但虚拟是大写的X,这显示小写的x).

在@ Annjawn的注释之后,将插入从V1_T1更改为T1中的直接插入工作正常(即插入了正确的值),并且奇怪地具有相同的计划哈希,即使它显示表名而不是名称列中的视图.同时使用UNION或UNION ALL,以及10gR2和11gR2.我猜,这似乎是工会混淆的触发器.

进一步到数据类型点…视图必须有char列,表不一定,这不是一个惊喜,因为视图上的触发器似乎是问题.如果我使用char列设置表但在视图中将它们转换为varchar2,那么我没有看到问题:

create table t1 (f1 varchar2(2),f5 char(2));

create view v1_t1 as select f1,f2,f3,cast(f4 as varchar(2)) f4,cast(f5 as varchar(2)) f5
from t1;

但如果我这样做,反过来确实表现出问题:

create table t1 (f1 varchar2(2),f4 varchar(2),f5 varchar(2));

create view v1_t1 as select f1,cast(f4 as char(2)) f4,cast(f5 as char(2)) f5
from t1;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读