2012-01-26 36 views
1

我有一个以冒号分隔的值列表存储在我的Oracle数据库的varchar2ORDER_PARTS_LIST列中。Oracle APEX数据库触发器 - 引用数据库列的问题

(据我所知,在这样的清单存储的数据可能不是最好的做法,但现在只是忽略了这个事实。)

下面是相关的表列:

ORDER_TABLE(
    ORDER_NUMBER number, 
    ORDER_PARTS_LIST varchar(4000)) 

PARTS_TABLE(
    PART_NUMBER varchar(20), 
    ASSIGNED_ORDER_NUMBER number) 

我有一个条件触发:

create or replace trigger "ORDER_PARTS_T1" 
BEFORE 
insert or update or delete on "ORDER_TABLE" 
for each row 
begin 
    if :new.ORDER_PARTS_LIST LIKE '%'+PART_NUMBER+'%' then 
    update PARTS_TABLE set ASSIGNED_ORDER_NUMBER = :ORDER_NUMBER; 
    end if; 

end; 

当我运行这触发我得到以下错误:

PLS-00201: identifier 'PART_NUMBER' must be declared 

什么是应该发生的是,这PART_NUMBERs,在PARTS_TABLE,包括在ORDER_PARTS_LIST触发检查,在ORDER_TABLE,然后插入ORDER_NUMBER,受影响的行ORDER_TABLE,进入​​列,的PARTS_TABLE

最后,ORDER中的所有零件应该标记为该ORDER的NUMBER。

这是否有任何意义?

我不确定如何正确地定义这个触发器中的变量,以便它可以运行,并且老实说,我有些怀疑触发器是否会做我认为应该做的事情,即使这些事情有效。任何建议或帮助获得像我已经定义的触发功能应该会很棒。提前致谢。

回答

1

你可以做字符串匹配测试每一行:

create or replace trigger "ORDER_PARTS_T1" 
BEFORE 
insert or update on "ORDER_TABLE" 
for each row 
begin 
    update PARTS_TABLE p 
    set p.ASSIGNED_ORDER_NUMBER = :new.ORDER_NUMBER 
    where instr(':' || :new.ORDER_PARTS_LIST || ':' 
      ,':' || p.PART_NUMBER || ':') > 0; 
end; 

因此,举例来说,如果ORDER_PARTS_LIST是'123:456:789',则INSTR将找到的ID 123,456和789的比赛,但不是124,45或8,例如。

当零件从订单中,您将需要一个不同的触发NULL相应的字段中PARTS_TABLE删除:

create or replace trigger "ORDER_PARTS_T1" 
BEFORE 
update on "ORDER_TABLE" 
for each row 
begin 
    update PARTS_TABLE p 
    set p.ASSIGNED_ORDER_NUMBER = NULL 
    where instr(':' || :new.ORDER_PARTS_LIST || ':' 
      ,':' || p.PART_NUMBER || ':') = 0 
    and instr(':' || :old.ORDER_PARTS_LIST || ':' 
      ,':' || p.PART_NUMBER || ':') > 0; 
end; 
+0

非常感谢您的先生!像魅力一样工作! – Spags

+0

就像一种跟进...你提到删除,我认为你是正确的,真的没有理由被列入,因为记录可能不会从数据库中删除。然而,有可能PART_NUMBERS在发送进行处理之前可以从订单中删除。如果零件已从订单中删除,是否有更新PARTS_TABLE的简单方法?我需要一个单独的触发器使用OLD和NEW等? – Spags

+0

也许 - 我用一个建议编辑了我的答案。 –

-1

不能完全确定这一切是如何结合在一起的(好像这将不考虑在多个订单相同的部分),但它看起来就像你正在试图做的是这样的:

create or replace trigger "ORDER_PARTS_T1" 
BEFORE 
insert or update or delete on "ORDER_TABLE" 
for each row 
begin 
    update parts_table 
    set assigned_order_number = :new.ORDER_NUMBER 
    where part_number in (:new.order_parts_list); 
end; 
+0

嗯......看来,如果只有一个PART_NUMBER已选定工作,但如果有倍数被选中它没有。它不会抛出错误,但它不会写入值。 – Spags

+0

@ Danimal37,不幸的是,你不能指望IN语句神奇地变成一个参数(':new。order_parts_list')到您想象的列表中。这就是为什么只有在选择了单个值的情况下才能工作。 –

+0

正确...您可能需要将每个元素都包含在单引号中才能正常工作。 –

0

您正在ORDER_TABLE上创建触发器。由于ORDER_TABLE不包含名为PART_NUMBER的列,Oracle无法找到标识符'PART_NUMBER',因为它属于PARTS_TABLE。

您需要在触发器中编写一个单独的查询以访问PARTS_TABLE中的PART_NUMBER。