0

我的目标是返回transaction_start价值。尝试了 RETURNING 关键字。

但在交易中它不起作用。结果没有错误。结果只是不包含任何数据。

还有其他方法可以实现这个目标吗?

BEGIN;
DELETE FROM table_for_tests WHERE item_id = '142';
INSERT INTO table_for_tests (item_id, valid, key, value) 
VALUES 
  ('142', tstzrange('1970-01-01T03:00', '1970-01-01T03:00:00.000100', '[)'), 'key1', 'modified value1'), 
  ('142', tstzrange('1970-01-01T03:00', '1970-01-01T03:00:00.000100', '[)'), 'key2', 'modified value2') 
RETURNING lower(transaction) as transaction_start;
COMMIT;

更新

table_for_tests架构:

id         | item_id  | valid               | transaction        | key           | value 
BIGSERIAL  | BIGINT   | TSTZRANGE NOT NULL  | TSTZRANGE NOT NULL | VARCHAR(255)  | VARCHAR(255) 

transaction在执行 INSERT、UPDATE 或 DELETE 操作时,触发器(posgresql temporal_tables扩展)会自动填充列。

触发器是由以下代码创建的:

CREATE TRIGGER versioning_trigger BEFORE INSERT OR UPDATE OR DELETE ON 
table_for_tests FOR EACH ROW 
EXECUTE PROCEDURE versioning('transaction', 'table_for_tests_history', true);

更新 2

的源代码trigger function (versioning),来自 pgAdmin III:

-- Function: public.versioning()

-- DROP FUNCTION public.versioning();

CREATE OR REPLACE FUNCTION public.versioning()
  RETURNS trigger AS
'$libdir/temporal_tables', 'versioning'
  LANGUAGE c VOLATILE STRICT
  COST 1;
ALTER FUNCTION public.versioning()
  OWNER TO postgres;
GRANT EXECUTE ON FUNCTION public.versioning() TO postgres;
REVOKE ALL ON FUNCTION public.versioning() FROM public;
COMMENT ON FUNCTION public.versioning() IS 'System-period temporal table trigger';
4

2 回答 2

0

RETURNING 子句不适用于事务级别,它适用于行级别。为处理的每一行返回一行。此外,该子句需要有效的选择,例如 * 或列名。尝试:

 insert into table_for_tests (item_id, valid, key, value) 
       values 
         ('142', tstzrange('1970-01-01t03:00', '1970-01-01T03:00:00.000100', '[)'), 'key1', 'modified value1'), 
         ('142', tstzrange('1970-01-01t03:00', '1970-01-01T03:00:00.000100', '[)'), 'key2', 'modified value2') 
      returning lower(valid) as transaction_start;

也许:

with do_ins  as  
     ( insert into table_for_tests (item_id, valid, key, value) 
       values 
         ('142', tstzrange('1970-01-01T03:00', '1970-01-01T03:00:00.000100', '[)'), 'key1', 'modified value1'), 
         ('142', tstzrange('1970-01-01T03:00', '1970-01-01T03:00:00.000100', '[)'), 'key2', 'modified value2') 
      returning lower(valid) as transaction_start
    )
select distinct transaction_start, count(*) over (partition by transaction_start)
  from do_ins;
于 2020-04-06T22:33:00.160 回答
0

用JOOQ解决了这个问题。

它有DSLContext方法transactionResult()

例子:

KeyValuesRecord record = context.transactionResult(tx -> {

tx.dsl().deleteFrom(KEY_VALUES)
            .where(KEY_VALUES.ITEM_ID.eq('142'))
            .execute();

KeyValuesRecord insertResult = tx.dsl().insertInto(KEY_VALUES, KEY_VALUES.ITEM_ID, KEY_VALUES.VALID, KEY_VALUES.VALUE)
        .values(itemId, range, value)
        .returning(KEY_VALUES.TRANSACTION)
        .fetchOne(); 

return insertResult;
});
于 2020-04-10T10:20:13.673 回答