我有postgresql表,它有一些独特的约束。
我有ruby脚本会更新此表。
ruby脚本应该能够切换到UPDATE而不是INSERT
当发生这种错误时:
PGError: ERROR: duplicate key value violates unique constraint
无论如何,下面的示例代码是我希望看到的,但显然不是:
@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
答案 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。