0

コード属性とインデックス属性を持つテーブルが 1 つあります。

コードの値をチェックするトリガーを作成しようとしています。挿入されたコードに重複がある場合、インデックスはトリガーされて 1 増加します。例:

code|c_index
111 | 1
112 | 1
113 | 1
111 | 2
114 | 1
112 | 2
111 | 3

これは私のコードですが、動作しません:

create trigger trg_update
after insert on trial

for each row

declare v_index;

begin

select max(nvl(trial.c_index, 0)) into v_index
from trial;

if new.code = code then
set new.c_index = v_index

else 
set new.c_index = 1

end if;
end;

................................................

私は新しいより良いものをやろうとしましたが、まだうまくいきません:

create trigger trg_update
after insert on trial
for each row
declare v_index number;

begin

if :new.code = :old.code then
select max(nvl(c_index, 0)) into v_index
from trial
where code = :new.code;

set :new.c_index = v_index + 1

else 
set :new.c_index = 1

end if;
end;

上記のコードの問題とその解決策は何ですか?

................................................................

アップデート:

このコードを実行した後:

create trigger trg_update
AFTER insert on trial
for each ROW

DECLARE v_index NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column
DECLARE v_cnt NUMBER   := 0;

BEGIN

SELECT MAX(c_index), COUNT(*)
  INTO :v_index, v_cnt
  FROM trial
 WHERE code = :new.code;

IF v_index <> -1 AND v_cnt > 1 THEN
--Only one update here, for the newly inserted row explicitly
  UPDATE trial
     SET c_index = c_index +1
   WHERE code    = :new.code
     AND c_index = v_index
     AND ROWNUM  = 1;

END IF;
END;

表示されるいくつかの問題:

1- エラー (2,1): PLS-00103: シンボル「DECLARE」が発生しました 2- エラー (7,8): PLS-00049: バインド変数 'V_INDEX' が正しくありません 3- エラー (9,15): PLS-00049 : 不適切なバインド変数 'NEW.CODE'

これは、エラー番号 2 と 3 を修正しようとした後の新しいコードです。

create or replace trigger trg_update
AFTER insert on trial
for each ROW

declare vindex NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column
declare vcnt NUMBER   := 0;

BEGIN

SELECT MAX(c_index), COUNT(*)
  INTO vindex, vcnt
  FROM trial
 WHERE code = :new.code;

IF vindex <> -1 AND vcnt > 1 THEN
--Only one update here, for the newly inserted row explicitly
  UPDATE trial
     SET c_index = c_index +1
   WHERE code    = :new.code AND c_index = vindex AND ROWNUM  = 1;

END IF;

END;

ただし、最初のエラーは引き続き表示されます。

エラー(2,1): PLS-00103: 次のいずれかを予期しているときに、記号「DECLARE」が検出されました: begin function pragma procedure subtype type current cursor delete exists before 続行するには、記号「begin」が「DECLARE」に置き換えられました。

このエラーに加えて:

Error(19,4): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge

How can I solve these errors??

4

2 に答える 2

0

この方法でトリガーを使用すると、多くのレベルで苦痛になることがわかります。最初は魅力的で、良いアイデアのように思えますが、そうではありません。

トリガーは、DRI が標準化される前に発明されました。それらの目的は、参照整合性を強制することです。可能な限り DRI を使用し、それ以外の場合は RI のみをトリガーする場合、DBMS との相性が大幅に向上します。

insert必要なことを行うには、(重複を挿入しないように) 行の存在をテストする相関サブクエリを使用するように変更しc_index、0に設定updateset c_index =c_index +1ます。

create procedure tablename_add @code int
as
-- add the row if it's not already there
insert tablename values (@code, 0)
where code not in 
      (select code from tablename where code = @code)
-- increase the count by one
update tablename set c_index = c_index + 1
where code = @code

トランザクションを定義する必要さえありません。行がない場合、INSERTは成功しc_indexてゼロに設定されます。それ以外の場合は効果がありません。その後、更新はc_index1関係なく増加します。

于 2013-04-17T06:59:48.837 に答える
0

まず、新しい値を挿入する前にデータベースにデータを設定し、次を実行します。

UPDATE trial tr
   SET c_index = (SELECT MAX(c_index) + 1
                  FROM trial
                 WHERE code = tr.code);

COMMIT;

その後、それに応じて値を更新するトリガーがあります(新しく挿入されたもの):

CREATE OR REPLACE TRIGGER trg_update
AFTER INSERT ON trial
FOR EACH ROW

DECLARE
v_index NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column v_cnt NUMBER := 0;

BEGIN

  SELECT MAX(c_index), COUNT(*)
    INTO v_index, v_cnt
    FROM trial
   WHERE code = :new.code;

  IF v_index <> -1 AND v_cnt > 1 THEN
  --Only one update here, for the newly inserted row explicitly
    UPDATE trial
       SET c_index = c_index +1
     WHERE code    = :new.code
       AND c_index = v_index
       AND ROWNUM  = 1;

  END IF;
END;

トリガーを編集しましたが、私の側ではうまく機能しますが、最初の更新クエリの後で正しく機能することに注意してください。DECLARE の問題が解決しない場合は、たとえばそれを削除してみてください。

于 2013-04-17T07:03:33.253 に答える