PostgreSQL 自定义运算符比较 varchar 和 integer



-- PostgreSQL 9.6.2 on x86_64-pc-linux-gnu,由 gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-17) 编译,64 位。

-- 从官方存储库安装。

-- postgresql.conf 中没有任何变化。

-- CentOS 6.8 版本。

-- 用户:邮政。

-- 由 BigSQL 使用 pgAdmin3 LTS。

-- 没有任何异常登录服务器。

我有很多疑问。

在这种情况下,我需要将字符变化的数据类型(可能是表字段)与整数值进行比较。

--结果是真还是假

select '10' = 10; 
select '10' = '10'; 
select '10'::character varying = '10'::character varying; 
select '10'::character varying = 'foo bar'; 
select '10'::character varying = 'foo bar'::character varying; 
select 'foo bar' = 'foo bar'; 
select '10'::character varying = '10';

--结果为"运算符不存在:字符变化 = 整数">

select '10'::character varying = 10; 

所以我创建了一个自定义运算符比较字符变化和整数

步骤 1:创建简单函数

CREATE OR REPLACE FUNCTION public.is_equal_char_int(character varying, integer) RETURNS boolean AS 
$BODY$ 
BEGIN 
IF $1 = $2::character varying THEN
RETURN TRUE;
ELSE 
RETURN FALSE; 
END IF;
End;
$BODY$ 
LANGUAGE plpgsql VOLATILE COST 100;

步骤 2:创建新运算符

CREATE OPERATOR public.=( 
PROCEDURE = is_equal_char_int,
LEFTARG = character varying,
RIGHTARG = integer);

所以我解决了我的问题,

select '10'::character varying = 10;

返回真值。

新的问题是: 当我将字符变化值与 unkown 数据类型值进行比较时,PostgreSQL使用我的自定义运算符

select '10'::character varying = 'foo bar';

结果是 :

整数的输入语法无效:"Foo bar">

select pg_typeof('foo bar');

返回未命名的数据类型。

下一步,我创建新的运算符来比较字符变化和unkown数据类型。

第 1 步:

CREATE OR REPLACE FUNCTION public.is_equal_char_unknown(character varying, unknown)
RETURNS boolean AS
$BODY$
BEGIN
IF $1 = $2::character varying THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
End;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;

第 2 步:

CREATE OPERATOR public.=( 
PROCEDURE = is_equal_char_unknown,
LEFTARG = character varying,
RIGHTARG = unknown);

当我跑步时

select '10'::character varying = 'foo bar';

我给

错误:运算符不是唯一的:字符变化 = 未知。

所以我在一个洞里。

要了解如何在 PostgreSQL 中为运算符进行类型解析,请阅读文档中的运算符类型解析规则。

在特殊情况下,步骤 3.a 之后仍保留以下运算符:

  • 您的自定义运算符 (character varying = integer)。

  • character = character(从character varyingcharacter的隐式转换)。

  • name = name(从character varyingname的隐式转换)。

  • text = text(从character varyingtext的隐式转换)。

然后,规则 3.c 选择您的运算符,因为它是唯一具有完全类型匹配的运算符。如果没有运算符,步骤 3.d 会选择text = text,因为text是字符串类别中唯一首选的类型。

您现在正在做的是发现为什么PostgreSQL中没有定义某些运算符,即为新类型组合定义新的比较运算符会导致歧义,从而导致错误,因为PostgreSQL无法决定使用哪个运算符。

问题的核心是PostgreSQL重运算符的能力,即拥有多个具有相同名称的运算符。然而,这是一个很好的功能,演员和操作员的系统已经经过精心平衡,以使体验尽可能好。unknown类型也是该系统的一部分。

换句话说,PostgreSQL试图猜测你的意思,但这并不总是可能的。如果你想比较一个(不是unknown)字符串和一个数字,你想要什么?它们应该作为数字还是字符串进行比较?'010'应该和10一样吗?PostgreSQL不知道你的意思,放弃了。

通过定义如何在 varchar 和数字之间进行转换,可以有另一种选择:

CREATE CAST (VARCHAR AS NUMERIC) WITH INOUT AS IMPLICIT;

这样就可以进行这样的比较:

SELECT '1'::character varying = 1::int;
> true
SELECT '01'::character varying = 1::int;
> true
SELECT '2'::character varying = 1::int;
> false
select '10'::character varying = 'foo bar';
> false

有关在 postgresql 中创建强制转换的更多信息,请单击此处: https://www.postgresql.org/docs/current/sql-createcast.html

最新更新