1

ある種の一意の制約があるpostgresqlテーブルがあります。

このテーブルを更新するrubyスクリプトがあります。この種のエラーが発生した場合、rubyスクリプトはINSERTではなくUPDATEに切り替えることができるはずです。
PGError: ERROR: duplicate key value violates unique constraint

CMIIW、続編はこの例外をキャッチできないようです??

とにかく、以下のサンプルコードは私が動作させたいものですが、明らかにそうではありません:

@myarray.each do |x|
        fresh_ds = DB["INSERT INTO mytable (id, col_foo) values ('#{x}' ,'#{myhash[x]}')"] 
        result = fresh_ds.insert

        catch Sequel::Error do

            fresh_ds = DB["UPDATE mytable set col_foo = '#{myhash[x]} where id = #{x}"]
            result = fresh_ds.update

        end

end

たぶん私のルビーコードが間違っているか、私が知らない何かを逃しました。
解決策はありますか?
ありがとう。

更新: 以下のコードは機能します。一意の制約に違反するとエラーがキャッチされます。

@myarray.each do |x|
    begin
      # INSERT CODE
    rescue Sequel::Error
      # UPDATE CODE
    end

end
4

2 に答える 2

1

この問題を解決するための代替パスは、Sequel::Modelのfind_or_createメソッドを使用します。

find_or_create (cond, &block)

findと同様ですが、レコードが存在しない場合、指定された条件でcreateを呼び出します。findとは異なり、このメソッドで使用されるブロックはfindに渡されませんが、findがオブジェクトを返さない場合にのみcreateに渡されます。

于 2011-01-14T19:58:54.643 に答える
1

まず、Rubyでのtry-catchは次のようになります

begin
...
rescue ExceptionClass => ex
...
end

もう1つは、クエリ全体を手動で作成するのではなく、Sequelのパラメーター補間を使用する必要があることです(主にSQLインジェクションのため)。

fresh_ds = DB["INSERT INTO mytable (id, col_foo) values (? ,?)", x, myhash[x]]

PS:

他の人がすでに指摘しているように、「挿入または更新」を実行する他の、おそらくより良い方法があります。一般に、例外は、例外、つまり実行中に通常は発生しないはずの条件を対象としています。あなたのケースはもっとif種類が多いので、最初SELECTに行がすでに存在するかどうかを確認するために使用するか、むしろUPDATE最初に変更された行の数を確認INSERTしてゼロかどうかを実行します。

于 2011-01-13T15:33:20.300 に答える