1

これは、MS SQLServer から PostgreSQL に変換したストアド プロシージャです。Postgresでそれを書くより良い方法はありますか? また、ベストプラクティスは何ですか?どんな助けでも大歓迎です。

create or replace function GenSerialNo_SP1(tname character varying) returns AS $$

--declare @PK bigint
declare totalRec bigint;
declare getRec bigint;
Begin

    --set @PK = 1
    set totalRec=-1;

    for getRec inselect coalesce(primary_key,0) from STD_SERIAL_NOS 
   where table_name = tname
    loop
    open  getRec;
    fetch next from getRec into totalRec;
    close getRec;
    deallocate getRec;
    end loop;
    if totalRec = -1 then

        insert into STD_SERIAL_NOS (TABLE_NAME, PRIMARY_KEY) values (tname, 1);

    else

        update STD_SERIAL_NOS set primary_key = primary_key +1 
           where table_name = tname;

    end if;

end;
$$ language plpgsql;
4

2 に答える 2

1

データベースの読み取り一貫性メカニズムにより、複数の同時プロセスが STD_SERIAL_NOS から同じ値を読み取り、それらの値を挿入/更新しようとする可能性があるという点で、あなたのアプローチには根本的な欠陥があります。

Postgres (または Oracle) でキー値を生成する正しい方法は、シーケンス オブジェクトを使用することです。おそらくトリガーを使用して、主キー列を自動入力します。

考えてみると、あなたが使用している方法は、おそらくどのデータベース システムにも欠陥があります。

于 2012-12-05T09:58:52.207 に答える
1

UPSERTのように見えますが、それを実現するカーソルは必要ありません。

に一意のインデックスがあると仮定するとSTD_SERIAL_NOS.table_name、挿入時の競合状態の処理を含む (うまくいけば) 正しいバージョンは次のようになります。

create or replace function GenSerialNo_SP1(tname character varying) returns void
as $$
begin
  loop
   begin
     update STD_SERIAL_NOS set primary_key = primary_key +1 
        where table_name = tname;
     exit when found; -- exit loop if the row exists, otherwise insert it
     insert into STD_SERIAL_NOS (TABLE_NAME, PRIMARY_KEY)
        values(tname,1);
   exception  WHEN unique_violation THEN
     -- the insert conflicts, let's go back to the update in the next loop iteration
   end;
  end loop;

end;
$$ language plpgsql;
于 2012-12-05T13:00:10.387 に答える