MySQL:独特的信息跨越2个表

时间:2016-06-22 21:31:52

标签: mysql sql indexing

我有两张桌子battles& battle_user

结构:

battles表:

id     create_date
1        2015/...

battle_user表:

id     battle_id     user_id
1          1           1
2          1           2

每场战斗中只有2位用户接受,问题是:是否有办法使用primary/foreign keys(或索引)来防止为同一2位用户插入另一场战斗?

防止这种情况:

battles表:

id     create_date
1        2015/...
2        2015/...

battle_user表:

id     battle_id     user_id
1          1           1
2          1           2
3          2           1
4          2           2
  

防止在相同的2个用户之间创建2场战斗

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,我不情愿地会展示如何以非规范化的方式使用一个独特的密钥,并且OP希望看到它。

这个概念是你知道用户,所以让他们楔入战斗表。然后你如何进入battle_users表取决于你,我建议不要改变。

create table battlesA1
(   id int auto_increment primary key,
    createDt datetime not null,
    user1 int not null,
    user2 int not null,
    -- FK Constraints go here (not shown, FK to users table)
    -- Then unique constraint goes here
    unique key(user1,user2) -- user1 is less than user2 on insert
    -- so on insert, utilize the least() and greatest() functions (mysql)
    -- or your front-end programming language
);

insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00',1,2);
-- success
insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00',1,2);
-- Error 1062, Duplicate Entry

least()greatest()示例:

set @user1:=14;
set @user2:=7;
insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00', least(@user1,@user2), greatest(@user1,@user2) );
-- success
insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00', least(@user1,@user2), greatest(@user1,@user2) );
-- Error 1062, Duplicate Entry


set @user1:=6;
set @user2:=700;
insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00', least(@user1,@user2), greatest(@user1,@user2) );
-- success
insert battlesA1(createDt,user1,user2) values ('2016-06-14 12:30:00', least(@user1,@user2), greatest(@user1,@user2) );
-- Error 1062, Duplicate Entry

drop table battlesA1; -- perhaps the best command you see here.

least(), greatest()LAST_INSERT_ID()的手册页。后者没有使用,但在这种情况下经常使用。

所以你有它。你想看到它,我并不是非常自豪地展示它。

答案 1 :(得分:0)

条件并不简单,目前在MySQL表中插入行之前创建复杂检查的唯一方法是触发器。

我创建了一个触发器,用于检查这些用户是否有其他记录,但是存在问题(可能):您需要删除未创建的战斗ID。

.basrc

在空表中执行我得到:

delimiter $$
drop trigger if exists `battle_user_bi`$$

create trigger `battle_user_bi` before insert 
    on `battle_user` for each row
begin
    declare msg varchar(100);
    declare usersInBattle int default 0;
    declare battleUsers int default 0;
    declare otherUser int default 0;

    set usersInBattle= (select count(*)
                    from  `battle_user` bu
                    where bu.battle_id = new.battle_id);


    if usersInBattle = 1 then  
        -- getting the other user
        set otherUser = (select user_id
                          from  `battle_user` bu
                          where bu.battle_id = new.battle_id);
        -- getting the same users in other battles
        set battleUsers = 
            (select count(*) from 
                (select bu.battle_id
                from  `battle_user` bu
                where bu.battle_id <> new.battle_id
                and bu.user_id = otherUser) 
              b1 inner join
                (select bu.battle_id
                from  `battle_user` bu
                where bu.battle_id <> new.battle_id
                and bu.user_id = new.user_id) b2 on b1.battle_id = b2.battle_id);


        if battleUsers > 0 then
            set msg = "There is already one battle for this users... ";
            SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
        end if;

    end if;

end$$
delimiter ;