简体   繁体   中英

How can I find out which table uses a specific foreign key value?

In my MariaDB database, I have three tables, Users , Workers and Admins , where the Users table has the column ID as primary key. Workers and Admins use a Users.ID as foreign (and primary) key. Users can either be Workers or Admins, not both. How can I find out, using a Users.ID , whether they are Workers or Admins?

I've tried this function:

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;

But this would just give me SQL syntax errors. Is a function the way to go here or is a simple IF clause enough?

Are you sure that one user cannot be Worker AND Admin simultaneously?

I'd do something like this instead:

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
    ...
;

You can do the same using sub-query instead of LEFT JOIN.

If you realy would like to use your way, you can do something like this:

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 ;

I would not use COUNT just to check existence as this is sub-optimal, Id would to the same.

I don't know if this solution is overkill to you but you can actually enforce a user to be either a worker "xor" an admin. This solution works starting on MariaDB 10.2.1.

You can use composite primary keys and CHECK constraints (that actually work in MariaDB 10.2.1 and newer).

For example:

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!

See? The last insert fails, so Tom cannot be an admin and a worker at the same time, and this is enforced at the database level, not your code.

Then, how do you know if it's an admin or a worker? Just look at the column type in the table users . Much simpler and cheap.

Cheers!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM