如何找出哪个表使用特定的外键值?

时间:2019-12-04 01:51:27

标签: mysql sql mariadb

在我的MariaDB数据库中,我有三个表UsersWorkersAdmins,其中Users表具有列ID作为主键。 WorkersAdmins使用Users.ID作为外键(和主键)。用户可以是Workers或Admins,不能两者都是。如何使用Users.ID来确定他们是工作者还是管理员?

我已经尝试过此功能:

CREATE FUNCTION workeroradmin(id INT)
    RETURNS VARCHAR(20)
BEGIN
    DECLARE type VARCHAR(20)
    IF (SELECT COUNT(*) FROM Workers WHERE ID = id) = 1 
    THEN
        SET type='Worker'
    ELSEIF (SELECT COUNT(*) FROM Admins WHERE ID = id) = 1
    THEN
        SET type='Admin'
    RETURN type;
END;

但这只会给我SQL语法错误。函数是到这里的方法还是简单的IF子句就足够了?

2 个答案:

答案 0 :(得分:0)

您确定一个用户不能同时成为Worker和Admin吗?

我会改成这样:

SELECT
      Users.Id
    , IF(Workers.Id IS NOT NULL, 1, 0) AS IsWorker
    , IF(Admins.Id IS NOT NULL, 1, 0) AS IsAdmin
FROM
    Users
    LEFT JOIN Workers ON (Workers.Id = Users.Id)
    LEFT JOIN Admins ON (Admins.Id = Users.Id)
WHERE
    ...
;

您可以使用子查询代替LEFT JOIN进行相同的操作。

如果您确实想使用自己的方式,则可以执行以下操作:

DELIMITER $$

CREATE FUNCTION `workeroradmin`(`_id` INT)
RETURNS varchar(20)
LANGUAGE SQL
BEGIN
    IF((SELECT `Id` FROM `Workers` WHERE `Id` = _id) IS NOT NULL) THEN
        SET @result = 'Worker';
    ELSEIF((SELECT `Id` FROM `Admins` WHERE `Id` = _id) IS NOT NULL) THEN
        SET @result = 'Admin';
    END IF;

    RETURN @result;
END$$

DELIMITER ;

我不会只使用COUNT来检查是否存在,因为这不是最优的,Id也会如此。

答案 1 :(得分:0)

我不知道此解决方案是否对您而言过于矫kill过正,但您实际上可以强制用户将其作为工作人员“异或”管理员。此解决方案从MariaDB 10.2.1开始有效。

您可以使用复合主键和CHECK约束(实际上在MariaDB 10.2.1和更高版本中有效)。

例如:

create table users (
  id int not null,
  type int not null check (type in (1, 2)),
  name varchar(20),
  primary key (id, type)
);

create table workers (
  id int not null,
  type int not null check (type = 1),
  position varchar(20),
  primary key (id, type),
  foreign key (id, type) references users (id, type)
);

create table admins (
  id int not null,
  type int not null check (type = 2),
  server varchar(20),
  primary key (id, type),
  foreign key (id, type) references users (id, type)
);

insert into users (id, type, name) values (100, 1, 'Anne'); -- worker
insert into workers (id, type, position) values (100, 1, 'Manager');

insert into users (id, type, name) values (105, 2, 'Tom'); -- admin
insert into admins (id, type, server) values (105, 2, 'server1');

insert into workers (id, type, position) values (105, 2, 'Programmer'); -- fails!

看到了吗?最后一次插入失败,因此Tom不能同时是管理员工作者,并且这是在数据库级别而不是您的代码上强制执行的。

然后,您如何知道它是管理员还是工人?只需查看表type中的列users。更简单,更便宜。

干杯!