【问题标题】:Date Subtraction on PostgreSQLPostgreSQL 上的日期减法
【发布时间】:2012-12-18 07:36:49
【问题描述】:

`我有一个表(workers),它有一个 startdate 列(s_date),表示员工何时开始工作。所以我想创建一个触发器,如果​​它的工作时间少于一年(365 天),我会给出一个例外。但是代码有问题。有什么帮助_?

CREATE OR REPLACE FUNCTION control_func() RETURNS TRIGGER AS '
declare 
int1 integer;
tt  Date;
begin 
select now()::date into tt;
select s_date from workers; 
if(tt-s_date<365) then
RAISE EXCEPTION ''A message'';
end if;
RETURN NULL;
END;
' LANGUAGE  'plpgsql';

【问题讨论】:

  • 如果有错误是什么?你不应该在 now() 和 a_date 上做一个date_part 吗?
  • @bonCodigo:表达式now()::date 仅返回日期。使用 CURRENT_DATE 是一个更好的主意。
  • @Catcall:使用current_date 还可以避免投射时可能出现的time zone problems
  • “代码有问题”。 始终显示您的 PostgreSQL 版本、代码和任何错误消息的完整文本

标签: sql database postgresql


【解决方案1】:

你有几个问题。首先,不要使用单引号来引用函数体,那样会造成很大的混乱,请改用dollar quoting

create or replace function f() returns trigger as $$
    ...
$$ language plpgsql;

接下来,这没有任何用处:

select s_date from workers;

这将尝试从workers 中获取所有s_date 值,然后将它们全部丢弃。您想查看触发器的当前行,这在NEW 中可用:

NEW
数据类型RECORD;为行级触发器中的INSERT/UPDATE 操作保存新数据库行的变量。此变量在语句级触发器和 DELETE 操作中为 NULL

所以您可以查看new.s_date 以查看您感兴趣的日期:

select now()::date into tt;
if tt - new.s_date < 365 then
    raise exception 'A message';
end if;

这可能是一个行级别的before insert or update 触发器,所以您不希望在这里使用return null;;来自fine manual

在操作之前触发的行级触发器有以下选择:

  • 可以返回NULL 跳过当前行的操作。这指示执行程序不执行调用触发器的行级操作(插入、修改或删除特定表行)。
  • 仅对于行级INSERTUPDATE 触发器,返回的行将成为将被插入或替换正在更新的行的行。这允许触发器函数修改正在插入或更新的行。

所以您的return null; 的意思是“如果新记录有效,则跳过此插入或更新”,这不是您想要的。你想return new;

您还有一个未使用的变量。您可以使用current_date 代替您的tt

你的函数应该看起来更像这样:

create or replace function control_func() returns trigger as $$
begin
    if current_date - new.s_date < 365 then
        raise exception 'A message'; 
    end if;
    return new;
end;
$$ language plpgsql;

【讨论】:

    【解决方案2】:

    编辑:初始语法应该是datediff。然而,它是一种 MYSQL 语法。因此,您最好使用上述详细而正确的答案。 ;-)

    在你的代码中输入这个, 添加另一个变量来保存s_date,比如ss

    If Datediff(days, tt, ss) &lt; 365 then

    【讨论】:

    • 你不需要date_part,PostgreSQL中两个date的区别是the number of days between them
    • @muistooshort 我从手机上输入了那个然后就走了。字典将datediff 翻转为date_part。您可能已经注意到它显然是 Datediff 语法进一步,我意识到这是 POSTGRES 而不是 MYSQL.... :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多