关于sql:Postgres:定义CAST失败的默认值?

Postgres: define a default value for CAST failures?

是否可以定义在CAST操作失败时返回的默认值?

例如,这样:

1
SELECT CAST('foo' AS INTEGER)

将返回默认值而不是抛出错误?


CAST没有默认值:

A type cast specifies a conversion from one data type to another. PostgreSQL accepts two equivalent syntaxes for type casts:

1
2
CAST ( expression AS TYPE )
expression::TYPE

除了要转换的表达式和所需的目标类型之外,语法中没有空间。

但是,您可以通过简单的功能手动完成:

1
2
3
4
5
6
7
8
CREATE OR REPLACE FUNCTION cast_to_int(text, INTEGER) RETURNS INTEGER AS $$
BEGIN
    RETURN CAST($1 AS INTEGER);
exception
    WHEN invalid_text_representation THEN
        RETURN $2;
END;
$$ LANGUAGE plpgsql immutable;

然后你可以说像cast_to_int('pancakes', 0)和get 0这样的东西。

PostgreSQL还允许您创建自己的强制转换,以便您可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
CREATE OR REPLACE FUNCTION cast_to_int(text) RETURNS INTEGER AS $$
BEGIN
    -- Note the double casting to avoid infinite recursion.
    RETURN CAST($1::VARCHAR AS INTEGER);
exception
    WHEN invalid_text_representation THEN
        RETURN 0;
END;
$$ LANGUAGE plpgsql immutable;

CREATE CAST (text AS INTEGER) WITH FUNCTION cast_to_int(text);

然后你可以说

1
SELECT CAST('pancakes'::text AS INTEGER)

得到0或你可以说

1
SELECT CAST(some_text_column AS INTEGER) FROM t

并获取0表示无效整数的some_text_column值。如果你想使用这个自动默认的强制转换投射varchar,那么你必须进行双重投射:

1
SELECT CAST(some_varchar::text AS INTEGER) FROM t

仅仅因为你能做到这一点并不是一个好主意。我不认为将标准文本替换为整数转换是最好的想法。上面的方法还要求你单独留下标准的varcharinteger,如果你想自己完成整个转换而不是懒洋洋地投入内置的转换,你可以绕过它。

NULL处理留给读者一个(简单)练习。


如文档中所述捕获错误,然后指定要执行的操作。

下面包含PostgreSQL Snippet错误捕获的文档。

35.7.5。陷阱错误

默认情况下,PL / pgSQL函数中发生的任何错误都会中止函数的执行,也会中止周围事务的执行。您可以使用带有EXCEPTION子句的BEGIN块来捕获错误并从中恢复。语法是BEGIN块的正常语法的扩展:

1
2
3
4
5
6
7
8
9
10
11
12
[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
EXCEPTION
    WHEN condition [ OR condition ... ] THEN
        handler_statements
    [ WHEN condition [ OR condition ... ] THEN
          handler_statements
      ... ]
END;

如果没有错误发生,这种形式的块只执行所有语句,然后控制传递到END之后的下一个语句。但是如果语句中发生错误,则放弃对语句的进一步处理,并将控制权传递给EXCEPTION列表。搜索列表以查找与发生的错误匹配的第一个条件。如果找到匹配项,则执行相应的handler_statements,然后控制传递到END之后的下一个语句。如果没有找到匹配,则错误传播出来,好像EXCEPTION子句根本不存在一样:错误可以被带有EXCEPTION的封闭块捕获,或者如果没有,则中止处理函数。