人大金仓数据库兼容mysql中truncate函数

关键字:KingbaseES、人大金仓、函数、truncate

函数调研

    1. mysql 8 truncate函数调研

语法:TRUNCATE(X, D)

其中,参数X是数值number类型,D是int整数类型,保留小数位数,函数返回值为number类型。如果D为0,则结果没有小数点或小数部分。D可以是负的,使值X的小数点左边的D位数变为0。

    1. kes trunc函数调研

有2种调用形式:

  • trunc(dp或numeric)
  • trunc(v , s)

第一种调用方式,传参可以是dp number或者numeric类型,若传入浮点数返回类型为numeric,若传入整数返回类型为double precision。

第二种调用方法中传参可以为

  • TRUNC(date),TRUNC(date [, fmt ]),传参为date,返回的值始终是数据类型 DATE,如果省略 fmt,则使用默认格式模型’ DD’,并且返回的值将被 date 截断为时间为午夜的日期。
  • TRUNC(number),TRUNC(n1 [, n2 ]),传参为number,此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果省略 n2,则 函数返回与参数的数值数据类型相同的数据类型。如果包含 n2,则函数返回 NUMBER。
  • TRUNC(text),trunc(text [, int]),第一个参数为 text 文本类型,并且需要为标准数字输入,没有范围限制。如果无法转换为标准数字,则报错。 如果第一个参数为 NULL 则返回 NULL。 第二个参数 int 如果省略,则将 text 文本截断为 0 位(即为整数)。如果 int 为负数,则截断小数点左侧的数字位数

推导分析

语句

Mysql

Kes

select truncate(122.123, 4);

截断数大于小数点的个数

122.123

122.1230

select truncate(0,3);

0

0.000

select truncate('',3);

0

Null

select truncate(' ',3);

0

报错

select truncate(1.2334,'');

1,warning

Null

select truncate(1.2334,' ');

1,warning

报错

select truncate('asd sdfjskdgjrei asdja',-1.8);

0,warning

报错

select truncate('2023-08-07',2);

2023,warning

报错

select truncate('2023-08-07 12:12:30',-9);

0,warning

报错

select truncate(date'2022-01-01',-1.8);

20220100

报错

select trunc(date'2023-08-08','year');

20230808,warning

2023-01-01

select truncate(1.2345,'12');

1.2345

1.23450 0000000

select truncate(122.123, 100000000000000000000);

122.123,warning

报错

select trunc(123.21);

报错

123

  1. 在mysql中如果截断数及第二个参数大于第一个参数小数点后面的总个数,直接返回该数本身,而在kes下会在小数点后面补零
  2. 在mysql中传参为’‘或’ ‘会默认为0,而kes下’‘默认null,’ ‘报错
  3. Mysql中不支持一个传参,kes一个参数可以认为是mysql中第二个参数为0,其结果一致
  4. 在mysql中字符串形式’…’(除’123‘这样数字字符串外)均会转换为number类型然后执行截断,但会提示warning,kes直接报错
  5. Mysql第一个参数最大支持10000000000000000000为八字节,kes第一个参数最大1000000000,是四字节大小

实现函数

3.1 用c语言方式实现

KDB_FUNCTION_INFO_V1(truncate);

Datum

truncate(KDB_FUNCTION_ARGS)

{

Numeric value = KDB_GETARG_NUMERIC(0);

int32 retainNum = KDB_GETARG_INT32(1);

Numeric res;

if(retainNum > 0)

{

NumericVar convert;

set_var_from_num(value,&convert);

if(retainNum > (&convert)->dscale)//value小数点后面有几个数

{

KDB_RETURN_NUMERIC(value);

}

else

{

res = DatumGetNumeric(DirectFunctionCall2(numeric_trunc, NumericGetDatum(value), Int32GetDatum(retainNum)));

}

}

else

{

res = DatumGetNumeric(DirectFunctionCall2(numeric_trunc, NumericGetDatum(value), Int32GetDatum(retainNum)));

}

KDB_RETURN_NUMERIC(res);

}

    1. 用plsql语言实现
  1. create function sys.truncate(numeric,int4)
  2. returns numeric
  3. as $$
  4. declare
  5.     value numeric;
  6.     result numeric;
  7. begin
  8.     value := length(substring(cast($1 as varchar), position('.' in cast($1 as varchar))+ 1));
  9.     if value < $2 then
  10.         return $1;
  11.     else
  12.         return (select trunc($1,$2));
  13.     end if;
  14. end;
  15. $$ language plpgsql;

在不直接调用kes下trunc函数的基础上实现mysql中truncate函数

create function sys.truncate1(numeric,int4)

returns numeric

as $$

declare

    left_value numeric; 

    right_value numeric; 

    temp varchar;

    temp1 varchar;

    res numeric;

begin

    left_value := length(substring(cast($1 as varchar), position('.' in cast($1 as varchar))+ 1));

    right_value := length($1 ::varchar) - left_value -1;

    if $2 >= 0 then

        if left_value <= $2 then

            return $1;

        else

            temp := substr(cast($1 as varchar), 1, right_value+1+$2);

            return TO_NUMBER(temp,'99999999999999999999.999999999999999999999999');

        end if;

    else

        if -$2 >= right_value then

            return 0;

        else

            temp := substr(cast($1 as varchar), 1, right_value-ABS($2));

            temp1 := RPAD(temp, ABS($2) + length(temp), '0');

            return TO_NUMBER(temp1,'99999999999999999999.999999999999999999999999');

        end if;

    end if;

end;

$$ language plpgsql;

参考资料

《KingbaseES SQL 语言参考手册》

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值