Postgresql - 排序后更新表的所有值

时间:2013-09-20 10:47:06

标签: postgresql sorting sql-update

在我的数据库中,我的记录如下:

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后填充此表中的条目。 有没有其他有效的方法来做到这一点?

5 个答案:

答案 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;