5

ここには奇妙な問題があります。自分で説明することはできません。

Oracle DB バージョン 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, F2, F3, F4, 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',   'Y',   '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, F2, F3, F4, 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',   'Y',   'GHJ',   'I',   'I'   FROM DUAL           
) A
ORDER BY 1, 2, 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 句に注意してください。これにより、最初の挿入ステートメントの最初の 3 行ではなく、すべての行が並べ替えられます。

編集: ORDER BY 句を省略した場合、結果も期待どおりになります (例 2 のように)。

誰かが私にこの動作を説明できますか?

PSコメントについて:

今日、このトピックについて調査したり、これ以上の情報を提供したりする時間はありません。データベースで完全な例を作成し、数日中にここに公開します。お待ちいただいてありがとうございます!

4

2 に答える 2

6

これは確かにバグのように見えますが、バグ データベースで明確な一致を見つけることができません (5842445 のようにいくつかの可能性がありますが、あいまいであるか、完全に一致していません)。トリガーでのみ実現できます(したがって、挿入は転記エラーT1ではなく反対であると想定しています)。およびでないV1_T1場合のみ:F4F5CHARVARCHAR2

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;

...そして、instead of質問に示されているとおりのトリガー。

:NEWによると、トリガー内の値は間違っていますが、それDBMS_OUTPUTが列のデータ型によってどのように影響を受けるかは、Oracleだけが理解できるものだと思います。

また、11.2.0.3 (Linux) でも発生します。興味深いことに、UNION ALLを justに変更するとUNION、わずかに異なる結果が得られます。10g では 2 つの列が null になり、11g では次のようになりますx

insert into v1_t1 (
  F1, F2, F3, F4, 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
    SELECT 'E',   'Y',   'QWE',   'O',   'E'   FROM DUAL UNION
    SELECT 'I',   'Y',   'GHJ',   'I',   'I'   FROM DUAL
) A
ORDER BY 1, 2, 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

...さらに奇妙です-おそらく他のバグの修正がこのバグにわずかに影響を与えているようです。

したがって、実際には答えではありません。order byOracle にサービス リクエストを提出する必要があります。ご存知のように、価値がないため、削除するように言われることは間違いありません。

ティロの場合。なしで計画するorder by(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 |
----------------------------------------------------------------------------------

order by 1,2,3 または 1,2,3,4,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 |
----------------------------------------------------------------------------------

また、他のテーブルからの選択でも同様の破損が見られますが、サブクエリの結果が順序付けられる前に結合されている場合のみです。ただし、ではなくnullを取得しxます。(がそれ自体xから来ているのかどうか簡単に疑問に思いましたが、大文字であり、これは小文字を示しています)。dualdummyXx


@Annjawnのコメントに従って、挿入をV1_T1直接挿入に変更すると正常に機能しT1(つまり、正しい値が挿入されます)、Name列のビューではなくテーブル名が表示されていても、不思議なことに同じ計画ハッシュがあります。または のいずれUNIONUNION ALLでも動作し、10gR2 と 11gR2 の両方で動作します。組合が混乱する引き金になりそうだな。


データ型のポイントに加えて...ビューにはchar列が必要ですが、テーブルには必ずしも列が必要ではありません。ビューのトリガーが問題のように見えるため、これは驚くことではありません。列を使用してテーブルを設定しても、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 f1, f2, f3, cast(f4 as varchar(2)) f4,
    cast(f5 as varchar(2)) f5
from t1;

しかし、逆にすると、問題が発生します。

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

create view v1_t1 as select f1, f2, f3, cast(f4 as char(2)) f4,
    cast(f5 as char(2)) f5
from t1;
于 2012-09-10T11:45:57.340 に答える