在sequel/ruby 中捕获 postgresql 异常有困难

发布于 2024-10-11 12:59:01 字数 814 浏览 7 评论 0原文

我有一个具有某种唯一约束的 postgresql 表。

我有 ruby​​ 脚本可以更新这个表。 ruby 脚本应该能够切换到 UPDATE 而不是 INSERT 当出现这种错误时:
PGError:错误:重复的键值违反了唯一约束

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

也许我的 ruby​​ 代码是错误的,或者我错过了一些我不知道的东西。
有什么解决办法吗?
谢谢。

更新: 下面的代码有效,当违反唯一约束时会捕获错误。

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

end

I have postgresql table that has somekind of unique constraint.

I have ruby script that will update this table.
The ruby script should be able to switch to UPDATE instead of INSERT
when this kind of error occured:
PGError: ERROR: duplicate key value violates unique constraint

CMIIW, sequel seems cannot catch this exception??

Anyway,sample code below is something that I would like to see to work but apparently not:

@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

Maybe my ruby code is wrong or I missed something I don't know.
Any solution?
Thanks.

UPDATE:
code below works, the error is caught when unique constraint is violated.

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

end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

未蓝澄海的烟 2024-10-18 12:59:01

首先,Ruby 中的 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。

First, try-catch in Ruby goes like this:

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

Another thing is that you should use Sequel's parameter interpolation instead of making whole query by hand (mainly because of SQL injection):

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

PS:

As others already pointed out, there are other, arguably better, ways to perform "insert or update". Generally, exceptions are meant for, er, exceptions, i.e. conditions that shouldn't normally happen during course of execution. Your case is more of if sort, so I would either first use SELECT to check whether row already exists, or, rather, try UPDATE first and see the number of changed rows and perform INSERT if it is zero.

故笙诉离歌 2024-10-18 12:59:01

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

find_or_create (cond, &block)

与 find 类似,但当记录不存在时,会根据给定条件调用 create。与 find 不同的是,此方法中使用的块不会传递给 find,而是仅在 find 不返回对象时传递给 create。

An alternate path to solve this problem uses Sequel::Model's find_or_create method:

find_or_create (cond, &block)

Like find but invokes create with given conditions when record does not exist. Unlike find in that the block used in this method is not passed to find, but instead is passed to create only if find does not return an object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文