Postgres:为 CAST 失败定义一个默认值?

Posted

技术标签:

【中文标题】Postgres:为 CAST 失败定义一个默认值?【英文标题】:Postgres: define a default value for CAST failures? 【发布时间】:2012-05-05 14:47:21 【问题描述】:

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

例如,这样:

SELECT CAST('foo' AS INTEGER)

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

【问题讨论】:

以这种方式更改默认/预期行为让我觉得……很危险。您希望能够使用IS_NUMERIC()(SQL Server 函数)之类的东西来检查该值,但对于 Postgresql(或 DB2,在我的情况下)似乎不存在。创建一个 UDF 可能会为您提供最好的服务,您也可以为其提供默认值。 哦,我不想更改功能 - 只需为该演员定义一个默认值(例如,CAST('foo' AS INTEGER DEFAULT -1) 之类的东西。 【参考方案1】:

CAST 没有默认值:

类型转换指定从一种数据类型到另一种数据类型的转换。 PostgreSQL 接受两种等效的类型转换语法:

CAST ( expression AS type )
expression::type

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

但是,您可以通过一个简单的函数手动完成:

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) 并得到0

PostgreSQL 还允许您create your own casts,因此您可以执行以下操作:

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);

那你可以说

select cast('pancakes'::text as integer)

然后得到0 或者你可以说

select cast(some_text_column as integer) from t

并获取0 以获取不是有效整数的some_text_column 值。如果您想使用此自动默认转换来转换 varchars,那么您必须进行双重转换:

select cast(some_varchar::text as integer) from t

仅仅因为你能做到这一点并不意味着它是一个好主意。我不认为将标准文本替换为整数转换是有史以来最好的主意。上述方法还要求您单独保留标准的 varcharinteger 演员表,如果您想自己进行整个转换而不是懒惰地使用内置演员表,则可以解决这个问题。

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

【讨论】:

只是想知道您是否可以澄清“注意双重转换以避免无限递归”?我原以为$1 已经是text/varchar 类型了。 @Bruno:函数是cast_to_int(text) 所以$1 将是texttextvarchar 是不同的类型。如果我们没有$1::varchar,那么我们将做一个cast(text as integer)。但是该转换是由 cast_to_int 函数实现的,因此 cast_to_int 最终会通过自定义转换间接调用自身。 啊,这很有趣,我错误地认为textvarchar 也会在那里be the more or less the same,但显然不是。 AFAIK textvarchar 之间的唯一区别在于 PostgreSQL 的最边缘,一旦您通过表面上的前几个分子,它们是相同的。这里有些人比我更了解内部细节。至少Craig Ringer 和Erwin Brandstetter 可能会注意到textvarchar 之间的区别,其中引用了这个和that one。【参考方案2】:

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

Documentation on error trapping for PostgreSQL 片段如下。

35.7.5。捕获错误

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

[ <<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 的封闭块捕获,或者如果没有,则中止函数的处理。

【讨论】:

以上是关于Postgres:为 CAST 失败定义一个默认值?的主要内容,如果未能解决你的问题,请参考以下文章

MEAN Stack:Cast to ObjectId 值“:id”失败

Postgres 时间戳列的默认值设置未正确使用

Mongoose,CastError:尝试保存包含模型的模型时,Cast to Array 的值失败

通过 JDBC 连接到 postgres 服务器时 sslmode 参数的默认值?

转换时SQL转换失败

如何在 cast sdk v3 中为投射按钮添加自定义样式?