我有下面的函数,我想传递anyelement
,它应该通过匹配正则表达式返回它是否是一个有效的URL:
CREATE OR REPLACE FUNCTION isURL(data anyelement)
RETURNS BOOLEAN
AS $$
BEGIN
RETURN data::text ~ '^https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{2,255}\.[a-z]{2,6}(\/[-a-zA-Z0-9@:%._\+~#=]*)*(\?[-a-zA-Z0-9@:%_\+.~#()?&//=]*)?$';
END
$$ LANGUAGE plpgsql;
当我运行以下命令时:
select isurl('https://example.com/submit');
它给出错误:
ERROR: could not determine polymorphic type because input has type unknown
如果我将输入数据转换为::text
,那么它就可以工作:
select isurl('https://example.com/submit'::text);
然而,这违背了我的anyelement
类型变量的目的。
error是什么意思?有没有一种方法可以在不进行铸造的情况下传递某个东西?我不介意函数内部发生的事情,只要在作为变量传递之前不需要强制转换。
2条答案
按热度按时间oymdgrw71#
恕我直言,我认为问题实际上在这里:“但是,这违背了我的任何元素类型变量的目的。”
Postgres的多态性有点有限,所以你可能期望它在某种程度上有用,但实际上并不是。
在postgres中使用anyelement的原因是,如果你要返回它或一个多态容器,如数组或范围。它实际上并没有示例化函数的新版本或延迟运算符或函数定义中的函数查找。
实际上,在示例中,您确实希望将参数声明为文本。然后,由postgres的隐式强制转换来决定是否可以在不进行显式强制转换的情况下传递其他类型--这通常是您想要的。
iq3niunx2#
虽然它可以是任何(标量)类型,但它必须是明确的类型。这意味着你需要清楚一个带引号的文字是什么类型。
'2021-03-31'
是什么类型的?你刚才说“短信”,不好意思,是约会。如果你说的是“日期”,不抱歉,这是一个零件编号存储为文本。“那没关系,我只是想要文本表示”你说。但恐怕这很重要。
类型化值的输入表示与它的标准类型表示 * 不 * 相同。因此,你的“引号中的东西”是文本、日期还是布尔值会产生真实的的差异。
这个问题只存在于文字,通常解析器可以根据上下文来解决。如果您将该值保存到日期列中,它将决定未知类型的引用文本必须是日期。但是函数并不显式地提供任何上下文,所以解析器没有任何可处理的东西。
因此,对于文字以外的任何东西(列、表达式、参数化查询值),您都应该很好(尽管您可能没有测试您认为自己是什么)。