Postgresql 如何测试给定的文本列是否是有效的oid
在PL/pgSQL中,我有一个列可能包含也可能不包含oid。我需要检测它是否存在 目前我是这样做的:Postgresql 如何测试给定的文本列是否是有效的oid,postgresql,plpgsql,typechecking,Postgresql,Plpgsql,Typechecking,在PL/pgSQL中,我有一个列可能包含也可能不包含oid。我需要检测它是否存在 目前我是这样做的: select oidtext from t into x where name = fname; if found then begin select x::oid into looid; exception when SQLSTATE '22P02' then -- invalid oid null; cr
select oidtext from t into x where name = fname;
if found then
begin
select x::oid into looid;
exception
when SQLSTATE '22P02' then -- invalid oid
null;
create or replace function oid_or_null(text)
returns oid language plpgsql immutable as $$
begin
return $1::oid;
exception when invalid_text_representation then
return null;
end $$;
select oid_or_null('123'), oid_or_null('abc');
oid_or_null | oid_or_null
-------------+-------------
123 |
(1 row)
但这感觉有点不舒服。是否存在阳性测试,即此文本列是有效的x类型,还是有效的强制转换?似乎唯一的方法是捕获异常,但您可以通过以下方便的函数执行此操作:
select oidtext from t into x where name = fname;
if found then
begin
select x::oid into looid;
exception
when SQLSTATE '22P02' then -- invalid oid
null;
create or replace function oid_or_null(text)
returns oid language plpgsql immutable as $$
begin
return $1::oid;
exception when invalid_text_representation then
return null;
end $$;
select oid_or_null('123'), oid_or_null('abc');
oid_or_null | oid_or_null
-------------+-------------
123 |
(1 row)
您可以创建更通用的布尔函数:
create or replace function is_valid_cast(text, text)
returns boolean language plpgsql immutable as $$
begin
execute format('select %L::%I', $1, $2);
return true;
exception when others then
return false;
end $$;
select
is_valid_cast('123', 'oid') as oid, is_valid_cast('abc', 'oid') as not_oid,
is_valid_cast('2018-10-10', 'date') as date, is_valid_cast('2018-20-20', 'date') as not_date;
oid | not_oid | date | not_date
-----+---------+------+----------
t | f | t | f
(1 row)
我的解决方案不需要捕获错误:
CREATE FUNCTION is_oid(text) RETURNS boolean
LANGUAGE sql IMMUTABLE STRICT AS
$$SELECT CASE WHEN trim(leading '0' from $1) ~ '^\d{1,10}$'
THEN $1::bigint BETWEEN 0 AND 4294967295
ELSE FALSE
END$$;
oid是一个4字节无符号整数,因此它必须由不超过10个数字组成,并且必须介于0和4294967295之间。我考虑过类似的方法,但这种解析可能有点不准确,例如“01234567890”::oid是有效的。我没有想到这一点;问题是没有内置的通用trycast或istype函数。当$1~'^0*\d{1,10}$'时,我将坚持使用基于异常的方法,或者在这种情况下使用。。。然后$1::bigint<4294967296…通用oid或某种类型的对象标识符,如regclass、'regproc`等?@ErwinBrandstetter在我的例子中oid将是一个较大的对象oid。对于公共对象标识符有一些方便的函数:to_regclass、to_regproc等。请参阅:但不适用于大型对象ID。这个值是一个有效的OID是否足够,或者你真的想检查它是否是一个有效的PGY-LARGEAR对象?LID?我想测试它是否是一个有效的OID,我知道它是Lo-OID或者一个向导,我会考虑Laurenz的函数,因为带有异常子句的函数要昂贵得多。