我正在尝试编写一个plpgsql函数来将记录插入到某些列中需要某些时间戳的表中。这是功能:
create or replace function insert_slot(created_by varchar
, version bigint
, bsv_id bigint
, start_date varchar) returns int as $$
declare
last_id int := (select id from appointments order by id desc limit 1) + 1;
begin
insert into appointments (
id,
created,
created_by,
version,
bsv_id,
usrn,
start_date,
end_date,
status,
request_priority_name,
reservation_expiry,
day_of_week
)values (
last_id,
now(),
created_by,
version,
bsv_id,
'UN-' || last_id,
to_timestamp(extract(epoch from timestamp @start_date)),
to_timestamp(extract(epoch from timestamp '2017-2-12 10:30:00')),
'OCCUPIED',
'ROUTINE',
to_timestamp(extract(epoch from timestamp '2017-3-19 10:30:00')),
1
);
return last_id;
end;
$$ LANGUAGE plpgsql;
select * from insert_slot('Brad', 2, 70000, '2017-2-12 10:00:00');
当我传递日期格式的文字字符串时,这可以正常工作,但不适用于参数:
to_timestamp(extract(epoch from timestamp @start_date)),
to_timestamp(extract(epoch from timestamp '2017-2-12 10:30:00')),
当我尝试使用@start_date
或start_date
而不是文字字符串时,我收到此错误:
ERROR: column "timestamp" does not exist LINE 21: to_timestamp(extract(epoch from timestamp @start_date)),
有人可以告诉我使用正确的语法吗?我在网上发现了很多关于使用参数的帖子,但找不到任何解决我无法通过时间戳将函数参数传递给epoch的内容。
答案 0 :(得分:1)
不要使用@
字符来添加变量。这种SQL-Server或MySQL语法(也许是其他语法)在Postgres SQL或PL / pgSQL代码中是非法的。
PL / pgSQL变量名遵循与SQL标识符相同的规则。 The manual:
SQL标识符和关键字必须以字母(
a-z
开头,但也必须以字母开头 带变音符号和非拉丁字母的字母)或下划线 (_
)。标识符或关键字中的后续字符可以是 字母,下划线,数字(0
-9
)或美元符号($
)。
所以 是语法错误。@start_date
在这个表达式中:
to_timestamp(extract(epoch from timestamp '2017-2-12 10:30:00')),
timestamp
是紧随其后的字符串文字的数据类型。
但是运行时类型转换不允许使用此表示法。所以这是一个语法错误:
<击> to_timestamp(extract(epoch from timestamp start_date))
击>
您可以使用显式类型转换:
to_timestamp(extract(epoch from start_date::timestamp))
::
,CAST()
和函数调用语法也可用于指定 任意表达式的运行时类型转换,如中所述 Section 4.2.9。为了避免语法歧义,type 'string'
语法 只能用于指定简单文字常量的类型。
在您的特定情况下,将函数参数定义为date
或timestamp
以开始时更智能/更清晰 - 取决于您计划传递给函数的数据类型。您的参数名称表示date
,但您的示例表示timestamp
。
无论哪种方式,你都不需要在以后投出。 EXTRACT()
也接受date
并自动将其投放到timestamp
。
答案 1 :(得分:0)
我建议您使用serial / bigserial作为id
:
CREATE TABLE appointments(id bigserial PRIMARY KEY, ...
最好将start_date作为timestsamp传递。
create or replace function insert_slot(created_by varchar, version bigint, bsv_id bigint, start_date timestsamp) returns int as $$
要在postgresql中访问函数的参数,只需使用其名称即可。您也可以通过<function_name>.<variable name>
拨打电话。当函数的参数与表中的列具有相同的名称时(在函数中),它可能很有用。为避免这种情况,您可以在名称中添加一些内容(例如v_
)。此外,您不需要太复杂的构造to_timestamp(extract(epoch from timestamp '2017-3-19 10:30:00'))
。你也可以使用sql函数。
改进的功能变体:
create table appointments (
id serial PRIMARY KEY,
created timestamp,
created_by text,
version text,
bsv_id int8,
usrn text,
start_date timestamp,
end_date timestamp,
status text,
request_priority_name text,
reservation_expiry timestamp,
day_of_week int2);
CREATE OR REPLACE FUNCTION set_usrn() RETURNS TRIGGER AS $sql$
BEGIN
NEW.usrn := 'UN' || NEW.id;
RETURN NEW;
END;
$sql$ LANGUAGE plpgsql;
CREATE TRIGGER insert_usrn BEFORE INSERT ON appointments FOR EACH ROW EXECUTE PROCEDURE set_usrn();
create or replace function insert_slot(v_created_by varchar, v_version bigint, v_bsv_id bigint, v_start_date timestamp) returns int as $$
insert into appointments (
created,
created_by,
version,
bsv_id,
start_date,
end_date,
status,
request_priority_name,
reservation_expiry,
day_of_week
)values (
now(),
v_created_by,
v_version,
v_bsv_id,
v_start_date,
'2017-2-12 10:30:00',
'OCCUPIED',
'ROUTINE',
'2017-3-19 10:30:00',
1
) RETURNING id;
$$ LANGUAGE sql;
检查结果:
select * from insert_slot('Brad', 2, 70000, '2017-2-12 10:00:00');
SELECT * FROM appointments;
id | created | created_by | version | bsv_id | usrn | start_date | end_date | status | request_priority_name | reservation_expiry | day_of_week
----+----------------------------+------------+---------+--------+------+---------------------+---------------------+----------+-----------------------+---------------------+-------------
1 | 2017-02-05 17:30:59.800305 | Brad | 2 | 70000 | UN1 | 2017-02-12 10:00:00 | 2017-02-12 10:30:00 | OCCUPIED | ROUTINE | 2017-03-19 10:30:00 | 1