难以在续集/红宝石中捕获postgresql异常

时间:2011-01-13 15:07:39

标签: ruby postgresql sequel

我有postgresql表,它有一些独特的约束。

我有ruby脚本会更新此表。 ruby脚本应该能够切换到UPDATE而不是INSERT 当发生这种错误时:
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

2 个答案:

答案 0 :(得分:1)

首先,Ruby goes like this中的try-catch:

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

另一件事是你应该使用Sequel的参数插值而不是手工制作整个查询(主要是因为SQL注入):

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

PS:

正如其他人已经指出的那样,还有其他可以说是更好的方法来执行“插入或更新”。通常,例外是指呃例外,即在执行过程中通常不应发生的条件。您的案例更多是if排序,因此我要先使用SELECT来检查行是否已存在,或者首先尝试UPDATE并查看已更改的行数并执行INSERT如果为零。

答案 1 :(得分:1)

解决此问题的另一种方法是使用Sequel :: Model的find_or_create方法:

  

find_or_create (cond, &block)

     

与find一样,但在记录不存在时调用给定条件下的create。与find不同,此方法中使用的块未传递给find,而是仅在find不返回对象时传递给create。