At a workplace they recycle punchcard ids (for some strange reason). So it is common to have past employees clashing with current employees. As a workaround I want to have employee punchcard id, employee name+surname as the unique primary key (fingers crossed, perhaps add date-of-birth and even passport if available). That can be accomplished with
PRIMARY KEY (pid,name,surname)
.
The complication is that another table now wants to reference an employee by its above primary key.
Alas, said PK has no name! How can I reference it?
I tried these but no joy:
PRIMARY KEY id (pid, name, surname),
INDEX id (pid, name, surname),
PRIMARY KEY id,
INDEX id (pid, name, surname) PRIMARY KEY,
Can you advise on how to achieve this or even how to reference a composite primary key?
Update:
The table to store employees is em
.
The table which references an employee is co
(a comment made by an employee).
Ideally I would use pid
(punchcard id) as the unique id of each employee. But since pid
s are recycled, this is not unique. And so I resorted to creating a composite key or an index which will be unique and can reference that as a unique employee id. Below are the 2 tables without the composite key. For brevity, I abbreviated table names and omitted surname etc. So the question is, how can I reference an employee whose id is composite from another table co
.
CREATE TABLE em (
pid INT NOT NULL,
name VARCHAR(10) NOT NULL
);
CREATE TABLE co (
id INT primary key auto_increment,
em INT,
content VARCHAR(100) NOT NULL,
constraint co2em_em_fk foreign key (em) references em(pid)
);
2
Answers
If another table wants to reference this one by a composite key, you don’t need it to have a name – just the list of fields will do. E.g.
UPD: If you expect that the set of the fields inside PK might change and you can’t make a simpler PK (auto-increment integer for example) for the original table, then your best bet might be something like this:
Then if you have a change in
employee
table PK, you’ll only need to updateemployee
itself andemployee_key
, any other tables would stay as is.If you CAN, however, change the original
employees
table, I would recommend something like this:Then you’ll have to maintain the logic of generating new pid’s in your code, though, or have them in some side table.
UPD2: Regarding inserts and updates.
As for inserts: you need to insert these explicitly – otherwise how would you expect the relation to be established? If you’re using an ORM library to communicate with your database, then it might provide you with the methods to specify linked objects without explicitly adding the IDs, but otherwise to insert a row into
employees
,employee_key
andother_table
you need to firstINSERT INTO employees(...) ;
, then get perform a separate INSERT for theemployee_key
(knowing the key fields you’ve just added toemployees
), get the auto-generated key fromemployee_key
and then use that to perform inserts to any other tables.You might simplify all this by writing an
AFTER INSERT
trigger foremployees
table (that would automatically create a row inemployee_key
) and/or performing your inserts via a stored procedure (that will even return back the key of the newly inserted row inemployee_key
). But still this work needs to be done, MySQL won’t do it for you by default.Updates are a bit easier, since you can specify
ON UPDATE CASCADE
when adding the foreign key – in that case a change to one of the fields in theemployees
will automatically trigger the same change in any tables that referenceemployees
by this key.You would define it
But you should read more about how MySQL uses INDEXES and how to optimize them
https://dev.mysql.com/doc/refman/8.0/en/optimization-indexes.html