根据外表的最后一个条目插入记录

时间:2018-05-27 11:00:18

标签: java sql postgresql postgresql-9.5

我有以下简单的表关系:

Expression.Call

" STATE"在Event中,从Java Enum转换,可以是:INITIALIZED,AVAILABLE,PROCESSED等。

我想执行以下操作:如果产品的最后一个事件条目具有STATE' PROCESSED',则在EVENT表中创建一个新的插入,其中STATE' AVAILABLE'。这必须适用于所有产品。

如您所见,事件表中包含对产品的引用。我查看了:Insert, on duplicate update in PostgreSQL?

但无法理解。

2 个答案:

答案 0 :(得分:1)

INSERT INTO EVENT( STATE, DATETIME, PRODUCT_ID )
SELECT 'AVAILABLE', current_timestamp, product_id
FROM EVENT e
WHERE PRODUCT_ID = 123
  AND e.STATE = 'PROCESSED'
  AND NOT EXISTS (
     SELECT 'anything' FROM event e1
     WHERE e1.PRODUCT_ID = e.PRODUCT_ID
       AND e1.DATETIME > e.DATETIME
);

如果此命令应该在多线程/多用户环境中运行,那么整个事务必须包含这四个命令,否则可能会出现重复记录:

BEGIN TRANSACTION;

/* lock the parent record */
PERFORM id FROM PRODUCT WHERE id = 123 FOR UPDATE;

INSERT INTO EVENT( STATE, DATETIME, PRODUCT_ID )
    SELECT 'AVAILABLE', current_timestamp, product_id
    FROM EVENT e
    WHERE PRODUCT_ID = 123
      AND e.STATE = 'PROCESSED'
      AND NOT EXISTS (
         SELECT 'anything' FROM event e1
         WHERE e1.PRODUCT_ID = e.PRODUCT_ID
           AND e1.DATETIME > e.DATETIME
    );

COMMIT;

答案 1 :(得分:1)

如果按顺序插入数据,我会更倾向于使用id进行比较,如下所示:

insert into event (state, datetime, product_id)
    select 'AVAILABLE', current_timestamp, product_id
    from event e
    where e.state = 'PROCESSED' and
          not exists (select e2.state
                      from event e2
                      where e2.product_id = e.product_id and
                            e2.id > e.id  -- you can use timestamp
                     );

我更感兴趣的是你说stateenum。 Postgres 支持enumerated types,但您没有。{但是,您要执行的操作通常使用检查约束来处理:

CREATE TABLE EVENT (
  ID               BIGSERIAL,
  STATE            VARCHAR(64) NOT NULL,
  DATETIME         TIMESTAMP   NOT NULL,
  PRODUCT_ID        BIGINT,
  FOREIGN KEY (PRODUCT_ID) REFERENCES PRODUCT(ID),
  PRIMARY KEY (ID),
  CONSTRAINT CHECK_EVENT_STATE CHECK (STATE IN ('INITIALIZED', 'AVAILABLE', 'PROCESSED'))
);
相关问题