【发布时间】:2020-04-18 23:54:45
【问题描述】:
我正在使用一个函数,如果该行不存在,则将其插入到表中,然后返回该行的 id。
每当我将函数放入 SELECT 语句中时,表中尚不存在值,例如:
SELECT * FROM table WHERE id = function(123);
... 它返回一个空行。但是,使用相同的值再次运行它会返回包含我想要查看的值的行。
为什么会这样? INSERT 是否落后于 SELECT 速度?还是PostgreSQL在表不存在时缓存表,下次运行时显示结果?
这里有一个现成的例子来说明这个问题是如何发生的:
CREATE TABLE IF NOT EXISTS test_table(
id INTEGER,
tvalue boolean
);
CREATE OR REPLACE FUNCTION test_function(user_id INTEGER)
RETURNS integer
LANGUAGE 'plpgsql'
AS $$
DECLARE
__user_id INTEGER;
BEGIN
EXECUTE format('SELECT * FROM test_table WHERE id = $1')
USING user_id
INTO __user_id;
IF __user_id IS NOT NULL THEN
RETURN __user_id;
ELSE
INSERT INTO test_table(id, tvalue)
VALUES (user_id, TRUE)
RETURNING id
INTO __user_id;
RETURN __user_id;
END IF;
END;
$$;
呼叫:
SELECT * FROM test_table WHERE id = test_function(4);
要重现该问题,请传递表中尚不存在的任何整数。
【问题讨论】:
-
这不是“速度”,它听起来像是事务可见性。考虑发布一个 full 示例,该示例还应显示 INSERT/UPDATE 关系。
-
我试着做一个更小的例子,完整的读起来很无聊
-
@user2864740 完成了一个非常简单的例子,我希望它能给你一些背景
标签: sql postgresql concurrency upsert