在我们的数据库中的两个表中使列唯一

时间:2011-10-04 10:19:36

标签: oracle

我在现有的公司遇到了一个帐户和成员。由于某种原因,两者都存储在单独的表中。

现在可以注册会员和帐户。这很好,除了会员和帐户的用户都可以使用相同的用户名。这当然是因为你们都知道错了。特别是因为他们使用用户名登录到同一系统,除了具有不同的功能级别。

现在我们正在应用程序级别进行检查,我们只是想知道是否有可能让数据库强制执行两个列是唯一的,比如两个表的并集。

目前无法将它们设置为主键或外键,但无论如何都是这样。现在正在寻找快速解决方案。在将来,我可能会合并数据库并将所有成员添加为帐户表中的新行,并为IsMember添加一个布尔值。

4 个答案:

答案 0 :(得分:4)

总的来说,我同意一致意见,即修复设计比使用触发器修复修复更好。但是,正确实施的基于触发器的解决方案仍然可能比您当前的情况更好。

如果您打算使用触发器,正确的方法是:

  1. 创建一个只包含用户名的新表,主键强制执行唯一性(事实上,这可能是一个非组织表的一个很好的候选者)。
  2. 在现有表上创建插入前触发器,将新用户名添加到新表中。如果新用户名已存在,则将引发错误,从而阻止插入两个行。当然,应用程序需要能够优雅地处理这个错误(可能已经可以,对于新用户名已经存在于它所添加的表中的情况)。
  3. 执行此操作的错误方法是从另一个表中选择触发器,以验证唯一性。

答案 1 :(得分:2)

您可以添加强制执行要求的trigger

答案 2 :(得分:1)

使用软删除模式时。 可以使用触发器(在每个表上)作为临时措施。

通过在另一个表中插入禁用的记录,如果另一个记录已经存在,则会出现故障

请记住,这不会对现有数据强制执行规则,只会检查插入的记录

这样的事情:

-- Insert into the accounts table too
CREATE OR REPLACE TRIGGER tr_member_chk 
BEFORE INSERT ON members
FOR EACH ROW 
BEGIN
    INSERT INTO account (name, id, etc, isenabled) VALUES(:new.name, :new.id, :new.etc, 0);
END;

-- Insert into the members table too
CREATE OR REPLACE TRIGGER tr_account_chk 
BEFORE INSERT ON accounts
FOR EACH ROW 
BEGIN
    INSERT INTO members (name, id, etc,isenabled) VALUES(:new.name, :new.id, :new.etc,0);
END;

答案 3 :(得分:1)

推荐的触发器在并发事务中往往非常脆弱。

您可以做的(AFAIK)是创建一个包含相关列的并集的物化视图,并在该列上添加唯一约束。

确保你做了一些性能测试。