2

シード データがテーブルに入力された後、一連のシーケンスを更新する SQL スクリプトがあります。以下のコードは機能しません。

declare
cursor c1 is 
    select
      'select nvl(max(id),0) from '||uc.table_name sql_text,
      uc.table_name||'_SEQ' sequence_name 
    from
      user_constraints uc,
      user_cons_columns ucc
    where uc.constraint_type='P'
      and ucc.constraint_name = uc.constraint_name
      and ucc.column_name='ID'
      and uc.owner='ME';

alter_sequence_text varchar2(1024);
TYPE generic_cursor_type IS REF CURSOR;
max_id number;
c2 generic_cursor_type;
begin
for r1 in c1 loop
    open c2 for r1.sql_text;
    fetch c2 into max_id;
    close c2;

    if( max_id != 0 ) then
        dbms_output.put_line( 'seq name = '||r1.sequence_name );
        execute immediate 'alter sequence '||r1.sequence_name||' increment by '||to_char(max_id);
        dbms_output.put_line( 'max_id = '||to_char(max_id) );
        execute immediate 'select '||r1.sequence_name||'.nextval from dual';
        dbms_output.put_line( 'sequence value = '||to_char(next_id) );
        execute immediate 'alter sequence '||r1.sequence_name||' increment by 1';
        dbms_output.put_line( 'sequence: '||r1.sequence_name||' is at '||to_char(max_id+1) );
    end if;
end loop;
end;

検索した後、行を変更する必要があると述べたリファレンスを見つけました。

execute immediate 'select '||r1.sequence_name||'.nextval from dual'

'into next_id;' を追加します。(もちろん、適切に next_id を宣言します) したがって、結果は次のようになります。

execute immediate 'select '||r1.sequence_name||'.nextval from dual into next_id;

私は pl/sql と sql を軽く扱っただけで、スクリプトを正しく機能させるためにこの変更が必要だった理由を知りたいと思っています。

ありがとう。

4

2 に答える 2

2

selectInsideブロックを使用してPL/SQLいる場合は、そのselectステートメントによって返されたデータをどこかに配置する必要があります。したがって、ステートメントがステートメントによって実行されselect intoている場合でも、適切なデータ型の変数を宣言し、句を使用してデータ選択リターンをその変数に入れる必要があります。selectexecute immediate

declare
  x number;
begin
  select count(*)
    into x
    from all_objects;
end;


declare
  x number;
begin
  execute immediate 'select count(*)from all_objects' into x;
end;

だからあなたのexecute immediate声明は

execute immediate 'select '||sequence_name||'.nextval from dual' into newseqval;

Oracle 11g以降を使用している場合は、シーケンスの値を変数に直接割り当てることができますselect into。句を使用する必要はありません。

 declare
   x number;
 begin
   x := Sequence_Name.nextval;
 end;
于 2012-09-23T07:18:01.813 に答える
0

select seq_name.nextval from dual は、暗黙的なカーソルの作成を意味し、カーソルの結果をどこかにフェッチする必要があるため、外部で宣言されたバインド変数にフェッチする必要があります。

于 2012-09-23T06:42:47.573 に答える