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
值。如果您想使用此自动默认转换来转换 varchar
s,那么您必须进行双重转换:
select cast(some_varchar::text as integer) from t
仅仅因为你能做到这一点并不意味着它是一个好主意。我不认为将标准文本替换为整数转换是有史以来最好的主意。上述方法还要求您单独保留标准的 varchar
到 integer
演员表,如果您想自己进行整个转换而不是懒惰地使用内置演员表,则可以解决这个问题。
NULL 处理留给读者作为一个(简单的)练习。
【讨论】:
只是想知道您是否可以澄清“注意双重转换以避免无限递归”?我原以为$1
已经是text/varchar
类型了。
@Bruno:函数是cast_to_int(text)
所以$1
将是text
、text
和varchar
是不同的类型。如果我们没有$1::varchar
,那么我们将做一个cast(text as integer)
。但是该转换是由 cast_to_int
函数实现的,因此 cast_to_int
最终会通过自定义转换间接调用自身。
啊,这很有趣,我错误地认为text
和varchar
也会在那里be the more or less the same,但显然不是。
AFAIK text
和 varchar
之间的唯一区别在于 PostgreSQL 的最边缘,一旦您通过表面上的前几个分子,它们是相同的。这里有些人比我更了解内部细节。至少Craig Ringer 和Erwin Brandstetter 可能会注意到text
和varchar
之间的区别,其中引用了这个和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”失败
Mongoose,CastError:尝试保存包含模型的模型时,Cast to Array 的值失败