Lon*_*Rob 6 postgresql postgresql-12
我有一张像:
CREATE TABLE foo(bar int)
Run Code Online (Sandbox Code Playgroud)
我有一个将值插入该表的脚本:
INSERT INTO foo(bar)
VALUES (1), (2), (3.2)
Run Code Online (Sandbox Code Playgroud)
浮点值被静默四舍五入以适合数据类型:
> SELECT * FROM foo;
bar
-----
1
2
3
(3 rows)
Run Code Online (Sandbox Code Playgroud)
Postgres 是否有任何内置功能可以防止这种情况发生,而是引发错误?(甚至是警告?)
数值常量3.2最初解析为数据类型numeric(不是float)。详细信息请参阅此处的手册。
对列的赋值会默默地进行,因为在标准 Postgres 中为-->integer注册了一个“赋值”转换。numericinteger
为了获得所需的行为,您必须在 Postgres 源代码中实现强制转换的函数中添加警告(并重新编译)。付出的代价非常高。(版本更新怎么样?)
或者您删除或更改已注册的演员。您可以用基于您自己的功能的版本替换演员 - 并WARNING在那里提出 a 。但这是昂贵的,并且可能会发出大量警告。
您不想完全删除该演员表。很多很多的计算都使用它。
您可以使用这个简单的解决方法:仅禁用事务的转换:
BEGIN;
UPDATE pg_cast
SET castcontext = 'e' -- make the cast "explicit"
WHERE castsource = 'numeric'::regtype
AND casttarget = 'integer'::regtype;
INSERT INTO foo(bar)
VALUES (1), (2), (3.2);
UPDATE pg_cast
SET castcontext = 'a' -- revert back to "assignment"!
WHERE castsource = 'numeric'::regtype
AND casttarget = 'integer'::regtype;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
现在,在实际输入的情况下会引发异常numeric。
但您需要超级用户权限才能执行此操作。您可以将其封装在一个SECURITY DEFINER函数中。有关的:
并且您不希望pg_cast在可能发生并发操作时长时间锁定系统目录。所以我不想在并发的情况下这样做。
您可以将输入值移动到 CTE 并在子句中进行测试WHERE,以跳过插入(静默)(如果它们不都是有效的整数值):
BEGIN;
UPDATE pg_cast
SET castcontext = 'e' -- make the cast "explicit"
WHERE castsource = 'numeric'::regtype
AND casttarget = 'integer'::regtype;
INSERT INTO foo(bar)
VALUES (1), (2), (3.2);
UPDATE pg_cast
SET castcontext = 'a' -- revert back to "assignment"!
WHERE castsource = 'numeric'::regtype
AND casttarget = 'integer'::regtype;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
db<>在这里摆弄
然后您可以检查命令标签是否插入了任何内容。
或者将其全部包装在 plpgsql 函数中,检查是否实际插入了任何内容,RAISE如果没有则检查您需要的内容。相关例子:
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |