触发更新一年中的一周

Trigger to update week of the year

我想写一个触发器,以便在插入或更新 decom_date 时将一年中的第几周更新为相应的值。

这是我目前的情况,但在插入日期后,星期仍然为空。

create or replace trigger test_trigger
before insert on check_decom
for each row
begin
if inserting then
update check_decom set decom_week= (select to_char(to_date(decom_date,'DD-
MON-YY'),'WW') as week from check_decom) ;
end if;
end;
/

SQL> select * from check_decom;

DECOM_DATE                     DECOM_WEEK
------------------------------ ----------
23-JUN-17

我做错了什么?

一年中第几周的示例

SQL> select to_char(to_date(sysdate,'DD-MON-YY'),'WW') as week from dual;
WE
--
28

你做错了几件事,从日期处理开始。您的 decom_date 列应定义为 DATE 列 - 看起来它可能是示例输出中的字符串。但是您对 sysdate 的处理也是错误的,因为您隐式转换为字符串以便将其转换回日期,这既没有意义又容易出错,因为这可能发生在具有不同的会话中NLS 设置。如果您的专栏实际上是 DATE 那么您也不应该针对它调用 to_date();如果它是一个字符串,那么该转换是有效的,但它 应该 DATE.

然后您的触发器正在查询并尝试更新触发器所针对的 table。没有数据不会出错但不会执行任何操作,因为没有要更新的现有行 - 您要插入的行尚不存在。如果有数据,你会得到一个变异 table 错误,如果你没有从 select 部分得到太多行异常。

行级触发器可以访问 NEW and OLD pseudorecords 以查看和操作受影响的行;您不需要(通常也不能)使用 DML 查询来访问您正在操作的行中的数据。

如果您的 table 是用日期列和数字列定义的:

create table check_decom(decom_date date, decom_week number);

那么您的触发器可能类似于:

create or replace trigger test_trigger
before insert on check_decom
for each row
begin
  if inserting then
    :new.decom_week := to_number(to_char(:new.decom_date, 'WW'));
  end if;
end;
/

尽管 if inserting 检查有点毫无意义,因为触发器只会在插入时触发。这本身可能是一个问题;您可能也希望在更新时设置它,但逻辑相同,所以会是:

create or replace trigger test_trigger
before insert or update on check_decom
for each row
begin
  :new.decom_week := to_number(to_char(:new.decom_date, 'WW'));
end;
/

哪个做你想要的:

insert into check_decom (decom_date) values (date '2017-06-23');

1 row inserted.

select * from check_decom;

DECOM_DAT DECOM_WEEK
--------- ----------
23-JUN-17         25

但我根本不会用触发器来做这件事。从 Oracle 11g 开始,您可以使用 a virtual column 代替:

create table check_decom (
  decom_date date,
  decom_week generated always as (to_number(to_char(decom_date, 'WW')))
);

Table CHECK_DECOM created.

insert into check_decom (decom_date) values (date '2017-06-23');

1 row inserted.

select * from check_decom;

DECOM_DAT DECOM_WEEK
--------- ----------
23-JUN-17         25