使用列来确定oracle表的显示顺序

时间:2011-10-07 18:54:26

标签: oracle plsql

我有一张表格,代表校园内的位置。我在网络程序中为用户显示这些位置,我想让他们能够更改位置显示的顺序。我有一个列,称为ord。我现在正在尝试为用户创建一种更新该列的方法,并确保这一点 1)没有ord个重复项 2)所有ord值都是> = 0&& < rowcount(表格)。

我想我应该用触发器来做这件事。首先,在我进行更新之前,我使用代码确保值为> = 0& < rowcount表。然后,一旦插入该值,我需要修复它创建的副本。我想要做的只是切换值。但是,当我尝试这个触发器时,我得到了可怕的oracle mutating表错误:

create or replace 
trigger plantry_campus_edit_after
after update on plantry_campus
for each row
declare 
  v_pkid number;
begin
  SELECT pkid INTO v_pkid FROM plantry_campus WHERE ord = :new.ord && pkid != :new.pkid;
  UPDATE plantry_campus SET ord = :old.ord WHERE pkid = v_pkid;
end;

我更喜欢在数据库中而不是在代码中执行此操作。有关如何实现这一目标的任何建议吗?

4 个答案:

答案 0 :(得分:1)

我会更改您的网络界面,以便他们可以在屏幕上重新排序,然后在保存时,只需按照现在屏幕上显示的顺序覆盖每行中的ord列。

答案 1 :(得分:0)

如果要执行此操作,请尝试使用包含plsql表类型的包变量。在行触发器中填充plsql表,然后在语句触发器中执行更新。这将解决变异表问题,因为语句级触发器在此方案中不受影响。

与此相似。

problem with trigger in oracle

请记住,包变量在整个会话期间都会持续存在,因此请在之前的触发器中初始化它们。

答案 2 :(得分:0)

您可以使用视图轻松解决变异表问题;虽然它不漂亮。更新视图并触发该视图:

您需要展开触发器以包含您要更新的所有列。

create or replace view v_plantry_campus_edit as select * from plantry_campus;


create or replace 
trigger plantry_campus_edit_after
after update on v_plantry_campus
for each row
declare 
  v_pkid number;
begin
  SELECT pkid INTO v_pkid FROM plantry_campus WHERE ord = :new.ord && pkid != :new.pkid;
  UPDATE plantry_campus 
     SET ord = :old.ord
         -- etc
       , col1 = :new.col1
   WHERE pkid = v_pkid;
end;

答案 3 :(得分:0)

恕我直言,在这种情况下使用触发器不是一个好主意,正如@Ben所说。我会在应用程序端重新排序表格,如下所示:

显而易见:

UPDATE plantry_campus SET
  ord = :new_order
where pkid = :pkid

重新订购更新:

If (:new_order > :old_order) then    
  UPDATE plantry_campus SET
    ord = ord + 1
  where pkid != :pkid
    and ord >= :new_order
    and ord < :old_order;
elsif (:new_order < :old_order) then
  UPDATE plantry_campus SET
    ord = ord - 1
  where pkid != :pkid
    and ord > :old_order
    and ord <= :new_order;
end if;

如果您不想在应用程序中执行此操作,只需将PL / SQL函数放入包中即可。