在两个表中强制使用唯一值

时间:2009-01-03 07:26:08

标签: mysql indexing

是否可以在MySQL中的两个表中强制实现唯一性?

我有两个表,都描述了用户。这些表中的用户以前用于两个不同的系统,但是现在我们正在合并我们的身份验证系统,我需要确保这两个表中有唯一的用户名。 (现在将它们全部放入一个表中是太多的工作了。)

7 个答案:

答案 0 :(得分:16)

您不能在多个表之间声明UNIQUE约束,并且MySQL根本不支持CHECK约束。但是您可以设计一个触发器来搜索另一个表中的匹配值。这是一个测试SQL脚本:

DROP TABLE IF EXISTS foo;
CREATE TABLE FOO (username VARCHAR(10) NOT NULL);

DROP TABLE IF EXISTS bar;
CREATE TABLE BAR (username VARCHAR(10) NOT NULL);

DROP TRIGGER IF EXISTS unique_foo;
DROP TRIGGER IF EXISTS unique_bar;

DELIMITER //

CREATE TRIGGER unique_foo BEFORE INSERT ON foo
FOR EACH ROW BEGIN
  DECLARE c INT;
  SELECT COUNT(*) INTO c FROM bar WHERE username = NEW.username;
  IF (c > 0) THEN
    -- abort insert, because foo.username should be NOT NULL
    SET NEW.username = NULL;
  END IF;
END//

CREATE TRIGGER unique_bar BEFORE INSERT ON bar
FOR EACH ROW BEGIN
  DECLARE c INT;
  SELECT COUNT(*) INTO c FROM foo WHERE username = NEW.username;
  IF (c > 0) THEN
    -- abort insert, because bar.username should be NOT NULL
    SET NEW.username = NULL;
  END IF;
END//

DELIMITER ;

INSERT INTO foo VALUES ('bill');  -- OK

INSERT INTO bar VALUES ('bill');  -- Column 'username' cannot be null

对于每个表,您还需要类似的触发器ON UPDATE,但是您不需要任何触发器ON DELETE。

答案 1 :(得分:4)

执行此操作的最佳方法是使用唯一列声明另一个表,并让多个表引用这些表

答案 2 :(得分:2)

也许不能直接回答你的问题,但是:

您应该考虑重写代码并重构数据库,将这两个表合并为一个。

您现在要强制执行的设计会使代码和数据库架构复杂化,并且会进一步升级到其他数据库软件或框架。

答案 3 :(得分:1)

您可以添加一个包含单个列的额外表作为主键。然后在每个旧用户表上创建一个触发器,将id插入到这个额外的表中。

create table users1 (
    user_id integer primary key,
    username varchar(8) not null unique
);
create table users2 (
    user_id integer primary key,
    username varchar(8) not null unique
);
create table all_usernames (
    username varchar(8) primary key
);
create trigger users1_insert before insert on users1 for each row
    insert into all_usernames values(new.username);
create trigger users2_insert before insert on users2 for each row
    insert into all_usernames values(new.username);
create trigger users1_update before update on users1 for each row
    update all_usernames set username = new.username
    where username = old.username;
create trigger users2_update before update on users2 for each row
    update all_usernames set username = new.username
    where username = old.username;
create trigger users1_delete before delete on users1 for each row
    delete from all_usernames where username = old.username;
create trigger users2_delete before delete on users2 for each row
    delete from all_usernames where username = old.username;

然后,您可以使用

填充表格
insert into all_usernames select username from users1;
insert into all_usernames select username from users2;

答案 4 :(得分:0)

显然,如果两个表中已经存在重复,则必须手动解决该问题。接下来,您可以编写一个触发器来检查两个表以查看该值是否已存在,然后将其应用于两个表。

答案 5 :(得分:0)

更改ID列的类型是否可以负担得起?然后,您可以选择GUID,这些GUID在您想要的任意数量的表中都是唯一的。

答案 6 :(得分:-1)

我不知道MySQL,但这是你在Oracle中可以做到的,我相信MySQL也支持物化视图。

您可以在这两个表上创建物化视图。并在此视图上添加唯一约束。

每次提交对两个基表之一的更改时,都需要刷新此视图。