1

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

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

4

5 回答 5

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

于 2013-09-20T11:39:05.773 回答
0

将另一个日期列添加到您的表中,这会使您的 start_date 条目加倍。使用触发器,您可以同步两者。如果你需要一个特殊的列名来阅读,你可以添加一个代表原始布局的视图。

在这种情况下,您有一个固定的主要日期列,但您与另一个列一起工作(阅读、更新)。

于 2013-09-20T10:54:11.220 回答
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

于 2013-09-20T11:16:30.310 回答
0

快速方法怎么样(仅针对此示例,假设您的日期接近现在)

update products set start_date = start_date + '50 year'::interval ;
update products set start_date = start_date - '49 year'::interval ;

我认为这不会产生重复的关键错误

于 2013-09-20T11:46:21.537 回答
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; 
于 2013-09-20T12:17:32.613 回答