在我的数据库中,我的记录如下:
Start_date | Product_code
2009-01-01 | 1
2010-01-01 | 1
...
...
我想将start_date更新为start_date + 1.
但我有(Start_date,product_code)作为我的主键
如果我执行我的查询
update products set start_date = start_date + '1 year'::interval ;
这会返回一个错误,指出已存在另一个条目(因为2010-01-01,1表已经是表中的条目)。
基本上,我需要在通过start_date按降序排序条目后进行更新
我可以通过创建另一个具有相同模式的表,以排序方式将所有条目复制到临时表,截断原始表,然后在添加start_date后填充此表中的条目。
有没有其他有效的方法来做到这一点?
答案 0 :(得分:2)
从Postgres 9.0开始,您可以定义可延迟的主键。这意味着它只会在您提交事务时检查,而不是每行检查。
create table products
(
start_date date not null,
product_code integer not null,
primary key (start_date, product_code) deferrable
);
insert into products
values
(date '2009-01-01', 1),
(date '2010-01-01', 1),
(date '2011-01-01', 1),
(date '2012-01-01', 1);
update products
set start_date = start_date + interval '1' year;
SQLFiddle:http://sqlfiddle.com/#!12/19b56/1
答案 1 :(得分:0)
将另一个日期列添加到您的表中,使您的start_date条目加倍。使用触发器,您可以同步两者。如果需要特殊的列名进行读取,则可以添加表示原始布局的视图。
在这种情况下,您有一个固定的主日期列,但您使用另一个列工作(阅读,更新)。
答案 2 :(得分:0)
这对我来说真的很奇怪(我通常使用SQL Server)。这篇文章可能对您有所帮助 - PostgreSQL: UPDATE a table using ORDER BY。这是从2007年开始,所以可能会有一些更优雅的解决方案。基于这篇文章的解决方案(不是我非常喜欢):
create view vw_products as select start_date from products order by start_date desc;
create rule vw_products_update as on update to vw_products
do instead update products set start_date = new.start_date where start_date = old.start_date;
update vw_products set start_date = start_date + '1 year'::interval;
<强> sql fiddle demo 强>
答案 3 :(得分:0)
如何快速进行(仅针对此示例,假设您的日期接近现在)
update products set start_date = start_date + '50 year'::interval ;
update products set start_date = start_date - '49 year'::interval ;
我认为这不会产生重复的密钥错误
答案 4 :(得分:0)
create or replace function update_order_by () RETURNS VOID as $$
DECLARE i RECORD;
BEGIN
FOR i IN SELECT * FROM product ORDER BY start_date DESC LOOP
UPDATE product SET start_date = i.start_date + '1 year'::interval WHERE start_date = i.start_date;
END LOOP;
END;
$$
LANGUAGE plpgsql;