PostgresQL 的 Verhoeff 校验和函数
Verhoeff Checksum function for PostgresSQL
我在以下位置找到了 PostgresSQL 的 Verhoeff 校验和函数:https://github.com/HIISORG/SNOMED-CT-PostgreSQL/blob/master/Verhoeff.sql
CREATE OR REPLACE FUNCTION verhoeff_generate (
input numeric = NULL::numeric
)
RETURNS smallint AS $$
DECLARE
_c SMALLINT := 0;
_m SMALLINT;
_i SMALLINT := 0;
_n VARCHAR(255);
-- Delcare array
_d CHAR(100) := '0123456789123406789523401789563401289567401239567859876043216598710432765982104387659321049876543210';
_p CHAR(80) := '01234567891576283094580379614289160435279453126870428657390127938064157046913258';
_v CHAR(10) := '0432156789';
BEGIN
_n := REVERSE(input::TEXT);
WHILE _i<length(_n) LOOP
_m := CAST(SUBSTRING(_p,(((_i + 1)%8)*10) + CAST(SUBSTRING(_n, _i+1, 1) AS SMALLINT) + 1, 1) AS SMALLINT);
_c := CAST (substring(_d, (_c *10 + _m + 1), 1) AS SMALLINT);
_i := _i + 1;
END LOOP;
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as SMALLINT));
END; $$
LANGUAGE 'plpgsql'
IMMUTABLE
RETURNS NULL ON NULL INPUT;
我修改了 RETURN,以便它将 INPUT 与校验和数字连接起来:
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as SMALLINT));
我得到错误:
[2020-02-20 11:53:19] [22003] ERROR: value "331010000014" is out of range for type smallint
[2020-02-20 11:53:19] Where: PL/pgSQL function verhoeff_generate(numeric) while casting return value to function's return type
我试过:
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as BIGINT));
仍然出现同样的错误。
您已经修改了提供 return 值的代码,从 returning 原来的 smallint 改为现在的字符串。 (CONCAT
函数输出一个字符串 - 在将数字输入 concat 之前,您可以任意多次转换数字,但它们将被转换为字符串,然后连接起来,并且concat 输出一个字符串,不管你输入什么)。
CONCAT 现在 return 给你一个包含太多数字的字符串(它的数字太大)以适应 smallint - PG 试图隐式地为你执行的转换。这代表核心问题:
CREATE OR REPLACE FUNCTION return_big_number ()
RETURNS smallint AS $$
RETURN '32769'; --string of a number that is too big for a smallint
END; $$
'32769'
是一个无法转换为 smallint 的字符串,因为它在数值上太大了 - smallint 的上限为 32767。同样,通过使用 concat,您将生成一个包含代表 a 的数字的字符串对于 smallint
来说数字太大
要么更改顶部的函数声明,使其return成为合适的字符串:
RETURNS smallint AS $$
^^^^^^^^
change this to perhaps "RETURNS text AS $$"
或者,如果将输出作为数字输出更适合您,请更改函数,使其声明为 return 可以表示比 smallint 更多数字的数字数据类型,然后更改 return 值计算以保持其数字(将输入乘以 10 的某个幂,然后添加校验和,而不是将输入更改为字符串并连接校验和)
我在以下位置找到了 PostgresSQL 的 Verhoeff 校验和函数:https://github.com/HIISORG/SNOMED-CT-PostgreSQL/blob/master/Verhoeff.sql
CREATE OR REPLACE FUNCTION verhoeff_generate (
input numeric = NULL::numeric
)
RETURNS smallint AS $$
DECLARE
_c SMALLINT := 0;
_m SMALLINT;
_i SMALLINT := 0;
_n VARCHAR(255);
-- Delcare array
_d CHAR(100) := '0123456789123406789523401789563401289567401239567859876043216598710432765982104387659321049876543210';
_p CHAR(80) := '01234567891576283094580379614289160435279453126870428657390127938064157046913258';
_v CHAR(10) := '0432156789';
BEGIN
_n := REVERSE(input::TEXT);
WHILE _i<length(_n) LOOP
_m := CAST(SUBSTRING(_p,(((_i + 1)%8)*10) + CAST(SUBSTRING(_n, _i+1, 1) AS SMALLINT) + 1, 1) AS SMALLINT);
_c := CAST (substring(_d, (_c *10 + _m + 1), 1) AS SMALLINT);
_i := _i + 1;
END LOOP;
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as SMALLINT));
END; $$
LANGUAGE 'plpgsql'
IMMUTABLE
RETURNS NULL ON NULL INPUT;
我修改了 RETURN,以便它将 INPUT 与校验和数字连接起来:
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as SMALLINT));
我得到错误:
[2020-02-20 11:53:19] [22003] ERROR: value "331010000014" is out of range for type smallint
[2020-02-20 11:53:19] Where: PL/pgSQL function verhoeff_generate(numeric) while casting return value to function's return type
我试过:
RETURN CONCAT(input, CAST(substring(_v,_c+1,1) as BIGINT));
仍然出现同样的错误。
您已经修改了提供 return 值的代码,从 returning 原来的 smallint 改为现在的字符串。 (CONCAT
函数输出一个字符串 - 在将数字输入 concat 之前,您可以任意多次转换数字,但它们将被转换为字符串,然后连接起来,并且concat 输出一个字符串,不管你输入什么)。
CONCAT 现在 return 给你一个包含太多数字的字符串(它的数字太大)以适应 smallint - PG 试图隐式地为你执行的转换。这代表核心问题:
CREATE OR REPLACE FUNCTION return_big_number ()
RETURNS smallint AS $$
RETURN '32769'; --string of a number that is too big for a smallint
END; $$
'32769'
是一个无法转换为 smallint 的字符串,因为它在数值上太大了 - smallint 的上限为 32767。同样,通过使用 concat,您将生成一个包含代表 a 的数字的字符串对于 smallint
要么更改顶部的函数声明,使其return成为合适的字符串:
RETURNS smallint AS $$
^^^^^^^^
change this to perhaps "RETURNS text AS $$"
或者,如果将输出作为数字输出更适合您,请更改函数,使其声明为 return 可以表示比 smallint 更多数字的数字数据类型,然后更改 return 值计算以保持其数字(将输入乘以 10 的某个幂,然后添加校验和,而不是将输入更改为字符串并连接校验和)