使用类型(&Quot;Text&Quot;)的字符串表示将值转换为类型(Text) [英] Cast value to type (TEXT) using string representation of type ("TEXT")
问题描述
我想创建一个函数,它试图将一组值转换为用户指定的类型(默认为文本)。一个非常简单的函数将如下所示:
CREATE OR REPLACE FUNCTION cast_to(variable jsonb, key text, target_type anyelement DEFAULT 'TEXT'::regtype) RETURNS anyelement as $$
begin
RETURN CAST(variable->>key AS target_type);
end
$$
language plpgsql;
我尝试了以下方法:
SELECT CAST('foo' AS 'text');
:给出语法错误SELECT CAST('foo' AS 'text'::regtype);
:与%1错误相同SELECT CAST('foo' AS pg_typeof(null::text));
表示type pg_typeof does not exist
最后一次尝试的想法是,我可以用目标类型传递一个变量,而不是文本表示形式。然后,使用该函数将看起来像SELECT cast_to('text', NULL::text);
。
如何实现此功能或类似功能?
编辑:正如评论中所建议的,我尝试使用动态SQL。我运气不太好。我创建了一个非常基本的案例,它不使用任何变量:
CREATE OR REPLACE FUNCTION audit.cast_to() RETURNS text as $$
DECLARE
_sql TEXT := 'SELECT CAST($1 AS $2)';
out TEXT;
begin
EXECUTE _sql
USING 'foo', 'TEXT'
INTO out;
return out;
end
$$
language plpgsql;
但引发错误:
syntax error at or near "$2"
推荐答案
实际上,这是可以做到的。即使没有动态SQL。表面上也很简单。
CREATE FUNCTION cast_to(_js jsonb, INOUT _target_type anyelement = NULL::text) AS
$func$
BEGIN
SELECT _js ->> pg_typeof(_target_type)::text
INTO _target_type;
END
$func$ LANGUAGE plpgsql;
数据库;>小提琴here
但这个极简主义函数包含了几个高级/棘手的细节:请参阅此处的最后一章了解基本信息:
难题的最后一块是将text
运算符返回的text
值转换为返回类型。一个简单的SQL函数对此要求很严格,不接受text
,比如说,一个integer
。(也不适用于由多态输入参数的实际输入定义的integer
。对于试图简单地RETURN
的PL/pgSQL函数也是如此。需要显式强制转换。
CAST (expression AS type)
is not a normal function。短句法expression::type
也不是。这些是构造或语法元素。您可能已经注意到类型名称不带单引号,即:asIDENTIFIER。(或您遗漏了该详细信息,这是您报告的前3个语法错误的原因。)并且不能在SQL中对标识符进行参数化。这将需要动态SQL。
但是,我们可以将表达式的text
结果赋给(必须键入的)变量或参数,以轻松实现相同的结果。INTO
子句将实现这一点。为方便起见,我直接给INOUT
参数_target_type
赋值。因此_target_type
有几个用途:
定义多态返回类型。
定义与JSON->>运算符一起使用的键名。该名称由
_target_type
的类型携带,我使用pg_typeof()
提取它-它实际上返回regtype
,因此我们需要将显式转换为文本。
注意:这始终会导致Postgres标准类型名称,例如:‘INTEGER’,而不是‘int’或‘int4’。如果您的密钥名称与默认的postgres类型名称不同,则必须像在原始设计中一样传递一个额外的参数!用作
OUT
参数(因此我们不需要DECLARE
变量),可以将其赋值给。有一个
DEFAULT
值:= NULL::text
,因此可以省略第二个参数,只返回text
。
您在原始版本中尝试了该功能,但偏离了目标。DEFAULT 'TEXT'::regtype
您可能希望将其中一些用途拆分为多个参数/变量。
这样就可以做到了。
问题是:您为什么要这样做?通常,有一个更快、更简单的解决方案--即使更冗长。
这篇关于使用类型(&Quot;Text&Quot;)的字符串表示将值转换为类型(Text)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!