PostgreSQL 在被除数=0时的小纯真和小倔强

标签

PostgreSQL , 被除数=0 , UDF , 自定义操作符


背景

0不能作为被除数,小学就学过的知识。

对于数据库来说,设计严谨,遵循一些基本的原则也是很有必要的。

当在数据库中除以0时,应该如何处理呢?

PostgreSQL为例,它具有非常浓烈的学院派风格,你说它你能让你除以0吗?

显然不让,如下:

postgres=# select 1/0;
ERROR: 22012: division by zero
LOCATION: int4div, int.c:719

代码中,我们可以看到对应的报错

Datum
int4div(PG_FUNCTION_ARGS)
{
        int32           arg1 = PG_GETARG_INT32(0);
        int32           arg2 = PG_GETARG_INT32(1);
        int32           result;  

        if (arg2 == 0)
        {
                ereport(ERROR,
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
                                 errmsg("division by zero")));
                /* ensure compiler realizes we mustn't reach the division (gcc bug) */
                PG_RETURN_NULL();
        }

但是,如果业务要求当被除数=0时,返回空,而不是报错,(又或者返回其他值)应该怎么处理呢?

除以0时返回空如何处理?

方法1

SQL标准中,有case的语法,可以用来支持被除数=0时返回其他值。

写法举例

select case when c2=0 then null else c1/c2 end from tbl ....;

方法2

自定义操作符

PostgreSQL允许用户自定义操作符,实现业务需求的逻辑

例子

create or replace function div_zero(numeric, numeric) returns numeric as $$
select case when $2 <> 0 then $1/$2 else null end ;
$$ language sql strict immutable;  

postgres=# create operator // (procedure=div_zero, leftarg=numeric, rightarg=numeric);
CREATE OPERATOR
postgres=# select 1//0;
 ?column?
----------  

(1 row)  

postgres=# select 1//1.1;
        ?column?
------------------------
 0.90909090909090909091
(1 row)

方法3

修改PG源码,新增一个GUC变量如enable_divs_zero,默认为off,则使用原有的处理方式。

当enable_divs_zero=on时,返回NULL.

例如对于INT类型,修改这个,其他类型修改对应的.c即可

Datum
int4div(PG_FUNCTION_ARGS)
{
        int32           arg1 = PG_GETARG_INT32(0);
        int32           arg2 = PG_GETARG_INT32(1);
        int32           result;  

        if (arg2 == 0)
        {
                // 加GUC判断,如果enable_divs_zero=off, 报错, 否则返回NULL
        ereport(ERROR,
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
                                 errmsg("division by zero")));  

                /* ensure compiler realizes we mustn't reach the division (gcc bug) */
                PG_RETURN_NULL();
        }

小结

PostgreSQL在很多方面都有一些学院派的小倔强,或者说趋于严谨的作风。

不过它很多开放的接口,所以,用户有什么特殊的需求,都是可以解决的。

时间: 2024-09-20 00:33:35

PostgreSQL 在被除数=0时的小纯真和小倔强的相关文章

重走0到100的路,小程序路在何方?

微信之父张小龙这样描述小程序:小程序是一种不需要下载安装即可使用的应用,它实现了应用"触手可及"的梦想,用户扫一扫或者搜一下即可打开应用.体现了"用完即走"的理念,用户不用关心是否安装了太多的应用这样的问题.应用将无处不在,随时可用,但又无须安装和卸载. 2011年1月,微信诞生,从2011年2月到4月,微信用户的增长并不快,所有的平台加起来每天也就增长几千人,那时候很多人不看好这个项目,甚至各种关于抄袭的质疑声不断传出. 张小龙当时是这么回应的:在微信3.0版本的

WinXP系统安装direct9.0时提示不能信任一个安装所需的压缩文件的解决方法

随着科技的发展,系统的升级越来越快,可是人们刚开始使用的xp系统已经习惯,升级的系统并不习惯,所以一些用户还是在使用着xp系统.最近,用户在安装direct9.0时,提示不能信任一个安装所需的压缩文件,应该如何解决呢?那现在就跟小编一起去看看WinXP系统安装direct9.0时提示不能信任一个安装所需的压缩文件的解决方法! 解决办法: 一. 首先大家先解压下载下来的软件压缩包,进行解压完之后,找到解压出来的软件,鼠标右键"以管理员方式"安装这个软件. 二. 假如大家是在安装游戏过程中

关于asp.net 1.0升级到asp.net 2.0时发现的一个有趣的问题

asp.net|问题     今天终于把原来的asp.net 1.0程序升级到asp.net 2.0了,vs 2005带有转换向导,一切自动化,操作比较方便.等它自动转换后,突然发现在App_Code文件夹里多了几个比较奇怪的文件都是stub开头的,并在一个mi开头的文件夹中(具体名称因为删除了,忘记了),因为原来根本就没有这些.cs文件,打开一看,原来都是抽象类,有几个还有抽象方法和共有字段.经过查看,才发现,原来在asp.net 1.0中有几个页面后置文件即.aspx.cs文件,里面有pub

编译安装php5.2.0时出错的解决方案

编译安装php5.2.0时出错解决方案 1.错误信息...................如下 checking for mcrypt support... no checking for mhash support... no checking whether to include mime_magic support... no checking for MING support... no checking for mSQL support... no checking for MSSQL

PostgreSQL 9.5.0 PK Oracle 12.0.1.2.0 TPC-C性能极限

Oracle 12c TPC-C 测试请参考: http://blog.163.com/digoal@126/blog/static/1638770402015112344924835/ 文件系统为XFS,优化手段如下: http://blog.163.com/digoal@126/blog/static/16387704020160695427218/ 本文在同样的硬件测试环境下对比PostgreSQL 9.5.0. 我们看看1月7号发布的PostgreSQL 新版本性能咋样? benchma

mvc 4-操作MVC 4.0时遇到的问题

问题描述 操作MVC 4.0时遇到的问题 1.在model层 有进行长度限制的验证,但是在客户端怎样才能实现当输入的字符超过限制的长度时,用户就不可以进行输入了呢? 2.为什么在model 定义子段为char 数据类型时,该字段映射不到数据库呢 3.客户端验证为什么为空好像就验证不了 谁能帮帮忙呢,我才接触MVC 4

mybatis Integer 值为0时,默认为空字符串

        在做一个简单的编辑功能时,发现有个字段一直修改不成功.  然后断点调试,发现integer为0时,竟然没执行以下代码:    <if test="is_publish != null and is_publish!=''"> is_publish = #{is_publish}    </if> 果断修改为:     <if test="is_publish != null"> is_publish = #{is_

cocos2d x-Cocos2d-X3.0引入头文件的一个小问题(希望大神帮助)

问题描述 Cocos2d-X3.0引入头文件的一个小问题(希望大神帮助) 假如我现在有一个Player.h的头文件 #include "Player.h"和直接class Player导入有什么区别 问什么我的有的时候#include "Player.h"这样导入会报 (error C2011: "Player":"class"类型重定义)错误 希望大神回答 解决方案 说明你的代码有变量冲突,具体看下错误的行.用命名空间区分下

用包含变量x的一个表达式实现:x&amp;amp;gt;0时结果为1,x=0结果为0,不要条件判断

问题描述 用包含变量x的一个表达式实现:x>0时结果为1,x=0结果为0,不要条件判断 用包含变量x的一个表达式实现:x>0时结果为1,x=0结果为0,不要条件判断. 可使用任意数学函数 解决方案 ?:当然是最容易想到的,但是这种回答没有任何帮助到你,肯定你也知道. 不知道什么语言,VB有Sign函数,>0返回1,=0返回0,<0返回-1 C++可以用 (int)(x > 0),原理是x>0返回true,转换成int是1 #include <iostream>