【发布时间】:2016-07-08 18:46:48
【问题描述】:
我和我的同事正在尝试在 PL/SQL 中编写一个数据库触发器,它可以查看映射表以从另一个表(下面包含示例表)中查找特定列的 ID,然后更新该列中的值.
我们需要能够将其作为 BEFORE EACH ROW 触发器来执行,以便我们在将数据提交到数据库之前对其进行修改。
我们最终编写了大量的 CASE 语句来处理这种情况,但有人知道处理这种情况的更好方法吗?在我们的实际示例中,我们还有 70 列可供查看,而不是 8 列,如下例所示。
create table test_basis (
id number(22,0) not null,
item_1 number(22,0) not null,
item_2 number(22,0) not null,
item_3 number(22,0) not null,
item_4 number(22,0) not null,
item_5 number(22,0) not null,
item_6 number(22,0) not null,
item_7 number(22,0) not null,
item_8 number(22,0) not null
)
create table basis_mapping (
column_id number(22,0),
column_name varchar2(35)
)
insert into basis_mapping(1, 'Company');
insert into basis_mapping(2, 'Account');
insert into basis_mapping(3, 'Manager');
insert into basis_mapping(4, 'User');
出于我们的目的,我们需要根据 column_name 从 base_mapping 中查找 column_id,然后更新当前行中的 :new.item_### 字段。因此,如果我们想更改“用户”列中的值,我们将运行以下语句
select column_id
into l_basis_id
from basis_mapping
where column_name = 'User'
现在我们在 l_basis_id 变量中有 4,我们如何使用它来生成如下语句?
:new.item_4 = 0
【问题讨论】:
-
通过动态sql.......?我没有在 oracle 中完成动态 slq,但这里有一个链接 docs.oracle.com/cd/B10501_01/appdev.920/a96590/adg09dyn.htm
-
当你开始有很多名为“item_xxx”的列时,我会说你的“test_basis”表设计有缺陷。也许你需要一个重复的、连接的表,或者另一个列,“item_name”,或者什么?
-
你的数据库设计看起来像一个键值模型(在关系数据库中不推荐)stackoverflow.com/questions/126271/…,但你的模型被开发到更高(更复杂)的抽象级别。最后考虑将表
test_basic规范化为三列:(id, column_id, item_value ) -
在 PL/SQL 中进行这种动态赋值并不容易。您应该将此作为一个指针,表明您对正在处理的任何业务问题都采取了错误的方法。您最好的选择是考虑一种适用于关系数据库系统的方法,或者坚持使用您的怪物 CASE 语句。
-
不幸的是,这是一个非常古老的系统,而且这些表非常集中,因此此时将模式修复为应有的状态并不是一个真正的选择。我确实很欣赏这些建议,但看起来我们现在必须坚持 CASE 声明。谢谢!