-3

`我有一个表(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';
4

2 回答 2

4

你有几个问题。首先,不要使用单引号来引用函数体,这只会弄得一团糟,请改用美元引号

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

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

select s_date from workers;

这将尝试从中获取所有s_dateworkers,然后将它们全部丢弃。您想查看触发器的当前行,该行位于NEW

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

所以你可以看看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;在这里;来自精美手册

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

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

因此,您的return null;意思是“如果新记录有效,则跳过此 INSERT 或 UPDATE”,这不是您想要的。你想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;
于 2013-01-03T22:11:11.897 回答
0

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

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

If Datediff(days, tt, ss) < 365 then

于 2013-01-03T21:28:38.577 回答