Sql 是“选择”吗;“更快”;而不是嵌套插入的函数?
我正在使用一个函数,如果表中不存在行,则将该行插入表中,然后返回该行的id 每当我将函数放入Sql 是“选择”吗;“更快”;而不是嵌套插入的函数?,sql,postgresql,concurrency,upsert,Sql,Postgresql,Concurrency,Upsert,我正在使用一个函数,如果表中不存在行,则将该行插入表中,然后返回该行的id 每当我将函数放入SELECT语句中时,其值在表中尚不存在,例如: 从id=function(123)的表格中选择*; 。。。它返回一个空行。但是,使用相同的值再次运行它将返回包含我希望看到的值的行 为什么会发生这种情况?INSERT是否在SELECT速度后面运行?或者,当表不存在时,PostgreSQL是否缓存该表,并在下次运行时显示结果 下面是一个随时可用的示例,说明了此问题是如何发生的: 创建表(如果不存在)测试表
SELECT
语句中时,其值在表中尚不存在,例如:
从id=function(123)的表格中选择*;
。。。它返回一个空行。但是,使用相同的值再次运行它将返回包含我希望看到的值的行
为什么会发生这种情况?INSERT
是否在SELECT
速度后面运行?或者,当表不存在时,PostgreSQL是否缓存该表,并在下次运行时显示结果
下面是一个随时可用的示例,说明了此问题是如何发生的:
创建表(如果不存在)测试表(
id整数,
t值布尔
);
创建或替换函数测试函数(用户id整数)
返回整数
语言“plpgsql”
作为$$
声明
__用户id整数;
开始
执行格式('SELECT*FROM test_table,其中id=$1')
使用用户id
输入用户id;
如果用户id不为空,则
返回用户id;
其他的
插入测试表(id,tvalue)
值(用户id,TRUE)
返回id
输入用户id;
返回用户id;
如果结束;
结束;
$$;
电话:
若要重现该问题,请传递表中尚不存在的任何整数。该示例在多个位置被打断
- 不需要使用
执行动态SQLEXECUTE
是错误的在函数中选择*
- 您的表定义应该在
上具有(id)
或唯一
约束主键
- 最重要的是,最后的
语句肯定会失败。由于(必须是),因此对表中的每个现有行计算一次。即使这样做有效,也将是一场性能噩梦。但事实并非如此。与@user2864740一样,可见性也存在问题。Postgres根据函数的结果检查每个现有行,该函数依次添加1行或多行,而这些行还不在SELECT
操作的快照中SELECT
从test_表中选择*,其中id=test_函数(4)代码>
选择
替换为:
SELECT * FROM test_function(1);
小提琴
相关的:
CREATE TABLE test_table (
id int PRIMARY KEY --!
, tvalue bool
);
CREATE OR REPLACE FUNCTION test_function(_user_id int)
RETURNS test_table LANGUAGE sql AS
$func$
WITH ins AS (
INSERT INTO test_table(id, tvalue)
VALUES (_user_id, TRUE)
ON CONFLICT DO NOTHING
RETURNING *
)
TABLE ins
UNION ALL
SELECT * FROM test_table WHERE id = _user_id
LIMIT 1
$func$;
SELECT * FROM test_function(1);