sql - 在 postgres 中从复合类型转换到复合类型

标签 sql postgresql casting composite

我在 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 替换为 varcharchar ):

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/

相关文章:

mysql - Toad for Mysql Server - 连接到远程主机时出现错误的握手错误

mysql - Left 函数遗漏字符

linux - 在本地 Windows 计算机中运行 postgres 命令时出现问题。在Linux、Mac下运行成功,但在windows下失败

c - C 中的函数指针困难,int (*foo(enum int var))(int)

go - 将界面转换为另一个界面并复制内容

sql - 具有新功能的 Asterisk

mysql - 如何加快获取每个用户最近交易的 AVG 的 MySQL 查询?

PostgreSQL:从两个表中选择计数和最大值

postgresql - 在 Postgres 中使用 INSERT INTO 与关联

c++ - 在 C++ 中转换指针