使用 TIMESTAMP 创建插入函数

问题描述

我用一个简单的函数创建了一个简单的表格,插入一些已过去学期的日志:

CREATE TABLE log_elapsedsemester(
sy char(9) NOT NULL,sem char(1) NOT NULL,date_recorded TIMESTAMP NOT NULL,recordedby varchar(255)
);

CREATE OR REPLACE FUNCTION addelapsedsemester(p_sy char,p_sem char,p_date_recorded 
TIMESTAMP,p_recordedby varchar)
returns void
AS
$$
BEGIN
insert into log_elapsedsemester (sy,sem,date_recorded,recordedby) values 
(p_sy,p_sem,p_date_recorded,p_recordedby);
END
$$
LANGUAGE plpgsql;

但我每次都用

select addelapsedsemester('2019-2020','1',Now(),'sample@gmail.com');

我收到错误

No function matches the given name and argument types. You might need to add explicit type casts.

如果我使用一个没有函数的简单 INSERT,它会成功插入:

insert into log_elapsedsemester(sy,recordedby) values ('2020- 
2021','sample@gmail.com');

我将 Postgresql 9.5 与 pgadmin III 一起使用。

解决方法

您需要显式转换为 timestamp。喜欢:

SELECT addelapsedsemester('2019-2020','1',now()::timestamp,'sample@gmail.com');

或者使用 LOCALTIMESTAMP 代替 now()::timestamp(等效)。

函数 now() 返回类型 timestamp with time zone (timestamptz),而您的函数接受 timestamp without time zone (timestamp)。 now() 函数产生一个 typed 值(与其他无类型文字不同),其中 Postgres 更不愿意将其强制为不同类型。 Function type resolution 没有成功。

相同类型的强制仍然适用于裸 INSERT 命令,因为 (quoting the manual):

如果任何列的表达式不是正确的数据类型,将尝试自动类型转换。

请注意,从 timestamptztimestamp 的转换取决于会话的当前 timezone 设置。您可能想要更明确。喜欢now() AT TIME ZONE 'Europe/London'。或者使用 timestamptz 开始。然后你没有演员的原始电话就可以工作。见:

此外,您很可能不想使用类型 char,它是 character(1) 的误导性短语法。请改用 textvarchar。见:

这个表定义更有意义:

CREATE TABLE log_elapsedsemester(
  sy varchar(9) NOT NULL,sem integer   NOT NULL,date_recorded timestamptz NOT NULL,recordedby text
);

甚至:

sy integer NOT NULL  -- 2019 can stand for '2019-2020'

函数参数将匹配列类型。