2014-12-30 10 views
5

嗨开发人员要求在默认值为'N'的表上添加列,但是如果条目具有id = 3,那么此列的默认值应该是'Y',无论如何,我可以在oracle中实现这个吗?Orace:基于过滤器的默认列值

+0

我通常从应用程序端处理这些事情。只是'column ='N'; if(id == 3)then column ='Y'; -----在DB中存储行------'。并且如果数据库中存在行,则只需使用'case when'语句更新现有行的列。 –

+1

可能会在插入过程中为此添加一个触发器? –

+1

具有'DECODE'功能的'VIRTUAL column'是您所需要的。 –

回答

0

11克方法

Oracle 11g及以上,你可以在一个步骤中使用VIRTUAL columns做到这一点。

测试用例

SQL> CREATE TABLE tab_default (
    2 ID   NUMBER, 
    3 flag varchar2(1) GENERATED ALWAYS AS (decode(id, 3, 'Y', 'N')) VIRTUAL 
    4 ); 

Table created. 

SQL> 
SQL> INSERT INTO tab_default (ID) VALUES (1); 

1 row created. 

SQL> INSERT INTO tab_default (ID) VALUES (3); 

1 row created. 

SQL> INSERT INTO tab_default (ID) VALUES (10); 

1 row created. 

SQL> SELECT * FROM tab_default; 

     ID F 
---------- - 
     1 N 
     3 Y 
     10 N 

SQL> 

所以,在VIRTUAL列声明的DECODE功能,为您处理的要求。

10克方法

您可以使用符合要求 -

  1. DEFAULT
  2. AFTER INSERT TRIGGER每当ID = 3

创建表有DEFAULT值“ N”。只有当新行插入值为id column = 3时,才触发触发器,以便触发器将值更新为'Y'。否则,对于所有其他情况,默认值为'N'。

+0

为什么要使用AFTER触发器而不是BEFORE触发器? –

+0

因为后触发至少确保事务向前移动。如果你在触发之前依赖,并根据这个做出改变,那么可能不是保证人。然而,在这种情况下,我不喜欢后续触发。顺便说一下,我不是触发器的巨大粉丝,因为它们是一种效果的动作,因此是一种副作用。但是,在这种情况下,如果有人不在'11g'上,那么这是唯一的方法。这是我编辑我的答案的主要原因,并将'11g'方法移到了'10g'触发器方法之上。 –

0

添加新列到表后,您可以在列使用以下查询插入值:在时间
1)决定列:

update table_name set column_name = (case when id = 3 then 'Y' else 'N' end);  

在插入新记录,你可以使用下面的方法创建插入查询,您可以在创建查询时为其添加逻辑。
2)在数据库中创建一个触发器,在向表中插入新行后,该触发器应更新列值。

0

这是一个很差的数据库设计。它不尊重关系数据库的正常形式。 我建议保持该表原样,并在表格上创建一个新的视图,并使用额外的列使用DECODE或CASE WHEN ...

+0

你的意思是糟糕的设计?不是电... – user2672165

+0

是糟糕的设计。我编辑了文本 – Charmi

+0

并非每个应用程序都可以在一夜之间修复。这就是为什么我们需要一些暂时的解决方案,直到找到并实施一个永久的解决方案。 –

0

我同意那些提到这不是一个好评论者数据库设计。也就是说,在数据库设计上做出妥协在现实生活中并不罕见。

我不确定虚拟列是需要的。 OP要求有一种默认的方式;虚拟列的工作方式与默认约束不同(例如,默认约束条件下,我们可以将非默认值插入列中。最佳路径可能是使用触发器设置“默认”值:

CREATE OR REPLACE TRIGGER mytrigger 
    BEFORE INSERT ON mytable FOR EACH ROW 
    WHEN (new.mycolumn IS NULL) 
BEGIN 
    SELECT DECODE(id, 3, 'Y', 'N') INTO :new.mycolumn FROM dual; 
END; 
/

触发器也将工作是否您正在使用Oracle 10g或11g(两者已经标记)。

希望这有助于。

+0

如果你使用':new.mycolumn:= CASE:new.id WHEN 3 THEN'Y'ELSE'N'END;'而不是'SELECT',你可以节省跳到PL/SQL引擎的成本引擎和后面只是为了执行IF测试。另外我不相信你对'id'的引用会在前面没有':new.'的范围内。我也欢迎在这里使用':old'而不是':new'的评论。 – Unoembre

+0

感谢您的评论,我认为您对所提到的一切都是正确的。也可能使用DECODE(:new.id,3,'Y','N')'而不是'CASE'等。 –

+0

请记住,'DECODE'只在SQL中有效,不能在PL/SQL中有效。 CASE在两者中均有效。 – Unoembre