如何从事务块中的 INSERT 语句中获取 return 值?
How to return value from INSERT statement in transaction block?
我的目标是returntransaction_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;
UPD:
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);
UPD 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';
RETURNING 子句在事务级别不起作用,它在行级别起作用。为处理的每一行返回一行。此外,该子句还需要有效的 select、so * 或列名。尝试:
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;
用 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;
});
我的目标是returntransaction_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;
UPD:
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);
UPD 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';
RETURNING 子句在事务级别不起作用,它在行级别起作用。为处理的每一行返回一行。此外,该子句还需要有效的 select、so * 或列名。尝试:
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;
用 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;
});