sql – 禁止“重复键值违反唯一约束”错误
我正在开发一个使用Postgres作为其数据库的Rails 3应用程序.我有下面的表格:
Table "public.test" Column | Type | Modifiers ---------------+---------+----------- id | integer | not null some_other_id | integer | Indexes: "test_pkey" PRIMARY KEY,btree (id) "some_other_id_key" UNIQUE CONSTRAINT,btree (some_other_id) 这有两列: > id,这是主键(由rails自动创建) 现在如果我尝试插入一个带有重复some_other_id的行,它会失败(好)并且我在Postgres日志中得到以下输出:
问题是我的应用程序尝试添加相同的ID两次是完全主线,并且我的日志被这个“错误”消息垃圾邮件,这会导致各种问题:文件占用大量磁盘空间,诊断会丢失噪音,Postgres必须扔掉diags以保持日志文件的大小限制等. 有谁知道我怎么能: >通过禁止有关此键的所有日志,或者通过在尝试执行INSERT的事务上指定某些内容来抑制日志. 请注意,任何解决方案都需要使用Rails,它执行如下插入: INSERT INTO test (some_other_id) VALUES (123) RETURNING id; 解决方法要避免重复键错误开始:INSERT INTO test (some_other_id) SELECT 123 WHERE NOT EXISTS (SELECT 1 FROM test WHERE some_other_id = 123) RETURNING id; 我假设id是一个自动获取其值的串行列. 这受到非常小的竞争条件(在SELECT和INSERT之间的时隙).但是可能发生的最糟糕的事情是你得到一个重复的密钥错误,这几乎不会发生,在你的情况下不应该是一个问题. 如果框架限制您使用正确语法的选项,则可以始终使用原始SQL. 或者您可以为此目的创建UDF(用户定义的函数): CREATE FUNCTION f_my_insert(int) RETURNS int LANGUAGE SQL AS $func$ INSERT INTO test (some_other_id) SELECT $1 WHERE NOT EXISTS (SELECT 1 FROM test WHERE some_other_id = $1) RETURNING id; $func$ 呼叫: SELECT f_my_insert(123); 或者,默认为已存在的ID: CREATE FUNCTION f_my_insert(int) RETURNS int LANGUAGE plpgsql AS $func$ BEGIN; RETURN QUERY SELECT id FROM test WHERE some_other_id = $1; IF NOT FOUND THEN INSERT INTO test (some_other_id) VALUES ($1) RETURNING id; END IF; END $func$ 同样,这为竞争条件留下了极小的机会.您可以以降低性能为代价来消除这种情况: > Is SELECT or INSERT in a function prone to race conditions? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |