2

このガイドに従ってブロックを作成しようとしてpl/sqlいますが、ORA-00922:missingまたはinvalidオプションが表示されますSET orderNumberSEQ...。私は何が間違っているのですか?

declare
orderNumberSEQ number(5);
userid varchar(20);

begin
insert into bs_orders (userid, ono, timepurchased)
values('lilith', orderNum_seq.NEXTVAL,(SELECT current_timestamp FROM dual));

SET orderNumberSEQ := orderNum_seq.CURRVAL;

SELECT userid FROM bs_orders
where ono = orderNumberSEQ;
end;
/
4

2 に答える 2

5

を使用する必要はありませんSET。ただ

SELECT orderNum_seq.CURRVAL INTO orderNumberSEQ FROM DUAL;

トリックを行います。または、次を使用する場合oracle11

orderNumberSEQ := orderNum_seq.CURRVAL;
于 2011-12-12T02:30:42.383 に答える
4

最初のアプローチにはいくつかの問題があります。選択された回答は、シーケンスの現在の値を決定する方法を正しく提供しますが、これらの問題には対処しません。

  1. シーケンスの値は、NEXTVAL と CURRVAL の呼び出しの間で変更された可能性があります。これにより、検出が困難なバグが発生し、別のセッションで使用される値を取得する可能性があります。実際に挿入された値を取得するには、insert ステートメントで return 句を使用します。
  2. 変数名は列名と同じです。これにより、PL/SQL ブロック内に埋め込まれたクエリのバグを検出するのが難しくなります。変数の名前が異なることを確認してください。ユーザー ID の代わりに v_userid のように、型名のプレフィックスを付けることができます。
  3. Oracle PL/SQL ブロック内の SELECT ステートメントには、INTO 句が必要です。例:

    SELECT userid INTO v_userid FROM bs_orders WHERE ono = orderNumberSEQ;

  4. current_timestamp のサブクエリは冗長です。サブクエリの代わりにプレーンな CURRENT_TIMESTAMP を使用して、同じ結果を得ることができます。

  5. 列の型を手動で指定する代わりに。%type 表記を使用して、正確なテーブル タイプに固定します。

    v_userid bs_orders.userid%type;

次のコードは、5 つの問題すべてに対処します。

DECLARE
 v_userid bs_orders.userid%type; -- anchoring the type
BEGIN
  INSERT INTO bs_orders(userid  , ono                 , timepurchased)
                 VALUES('lilith', orderNum_seq.NEXTVAL, CURRENT_TIMESTAMP)
  RETURNING userid INTO v_userid; -- instead of currval and an additional select
  -- do whatever you want with v_userid here
END;
/
于 2011-12-12T08:09:32.280 に答える