我在 postgres 中创建了一个复合类型:
CREATE TYPE mytimestamp AS (t timestamp with time zone, o int);
并将其添加到表中
CREATE TABLE t (t0 mytimestamp)
使用自定义转换函数和以下 CAST,我能够将带时区的简单时间戳转换为 INSERT 语句中的“mytimestamp”:
CREATE CAST (timestamp with time zone AS mytimestamp)
WITH FUNCTION to_mytimestamp(timestamp with time zone) AS ASSIGNMENT;
INSERT INTO t (t0) VALUES(now()); -- works as intended
但是,我似乎无法创建适用于以下语句的 CAST:
CREATE CAST (varchar AS mytimestamp)
WITH FUNCTION to_mytimestamp(varchar) AS ASSIGNMENT;
INSERT INTO t (t0)
VALUES('2014-09-11 13:30:12.564+02'); -- returns 'malformed record literal'
(我需要从 varchar、char 或 text 进行转换——但简单地实现转换函数并添加相应的 CAST 似乎不起作用)
我知道我可以通过将查询更改为
来实现这一点INSERT INTO t (t0)
VALUES('2014-09-11 13:30:12.564+02'::varchar); -- works
-- the to_mytimestamp(varchar) function is called
但是在我的例子中,我无法更改查询,因为它们是在某些不应再更改的代码中定义的。
有没有办法确保在执行上述 INSERT 语句时调用 to_mytimestamp(varchar)
函数(无需附加 ::varchar
)?
非常感谢!
编辑:
以下是提到的函数(根据需要将 to_mytimestamp()
中的 text
替换为 varchar
或 char
):
CREATE OR REPLACE FUNCTION to_mytimestamp(t text)
RETURNS mytimestamp AS
$BODY$
declare
ts mytimestamp;
offs text;
matches text[];
begin
offs = substr(t, length(t) - 5, 6);
matches = regexp_matches(offs, '[+-][0-9.:]*', 'g');
offs = split_part(matches[1], ':', 1)::integer * 3600 + split_part(matches[1], ':', 2)::integer * 60;
ts.t = t::timestamp with time zone;
ts.o = offs;
return ts;
end
$BODY$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION to_mytimestamp(t timestamp with time zone)
RETURNS mytimestamp AS
' select $1, extract(timezone from $1) '
LANGUAGE sql;
说明:函数提取 utc 偏移量并将其存储在单独的值中以供以后重建。
注意:to_mytimestamp(t timestamp with time zone)
存储系统偏移量,而不是假设存储在参数 t
中的偏移量,因为 timestamp with time zone 不实际上包含偏移数据 - 但这与问题无关:)
最佳答案
我认为你做不到。
当您在 postgres 中编写字符串文字 'foo'
时,它实际上具有“未知”类型,而不是文本。因此,您的转换函数不匹配,因为类型不同。这就是为什么你可以这样做:
SELECT '2014-09-11 13:30:12.564+02'::text::mytimestamp;
它会按预期工作。
即使您编写的函数版本将 unknown
处理为参数类型(并首先将其转换为 text
),并创建相关的转换:
CREATE CAST (unknown AS mytimestamp)
WITH FUNCTION mytimestamp(unknown)
AS IMPLICIT;
Postgres 仍将尝试使用原来的复合类型转换功能。事实上,这打破了“convert-to-text-first”路径,因为没有更好的匹配mytimestamp(text)
,所以它使用内置函数。
关于sql - 在 postgres 中从复合类型转换到复合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25786595/