SQL 和外键的逻辑问题
Logical Trouble with SQL and foreign key
已编辑*1
我是软件开发人员的实习生,所以我对 MySQL-数据库没有太多经验。
我想为任务写一个工单,它包含了工人的详细信息以及需要哪个工人。
我在数据库中有一个 table,其中包含工人的姓名和部门。
table worker
看起来像这样:
+---------+---------+----------+------------+
| id (PK) | surname | forename | department |
+---------+---------+----------+------------+
| 1 | bar | foo | shop |
+---------+---------+----------+------------+
| 2 | baz | foo | production |
...
而 table tasks
看起来像这样:
+---------+------------+----------+-------------+----------------+-------------------+----
| id (PK) | task | shop_req | shop_worker | production_req | production_worker | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 1 | do sth. | yes | 1 | yes | 2 | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 2 | do sth. | no | (NULL) | yes | 2 | ...
...
如何将它们连接在一起?
我试过这个SQL-代码:*1
ALTER TABLE tasks
ADD CONSTRAINTS FK_tasks_shop
FOREIGN KEY (shop_worker)
REFERENCES worker(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
ADD CONSTRAINTS FK_tasks_production
FOREIGN KEY (production_worker)
REFERENCES worker(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
当我使用以下 SQL-代码调用 table tasks
时:
SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
JOIN worker AS b ON a.shop_worker = b.id
JOIN worker AS c ON a.production_worker = c.id
结果是:
+----+------+----------+-------------+----------------+-------------------+----
| id | task | shop_req | shop_worker | production_req | production_worker | ...
+----+------+----------+-------------+----------------+-------------------+----
表示结果只有列名,没有行。
我希望得到以下结果:
+----+------------+----------+-------------+----------------+-------------------+----
| id | task | shop_req | shop_worker | production_req | production_worker | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 1 | do sth. | yes | bar, foo | yes | baz, foo | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 2 | do sth. | no | (NULL) | yes | baz, foo | ...
...
这里有什么问题?我找不到错误。
有没有有效的方法调用SQL-代码?
非常感谢您的回答!
首先,您的查询缺少 tasks
的 AS a
别名,这会使查询失败。添加后,您应该返回一行,但是 ...
因为您想要包含 tasks
table 中的所有行,即使 shop_worker
或 production_worker
没有匹配的行,您也需要使用left join
而不是像这样:
SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
LEFT JOIN worker AS b ON a.shop_worker = b.id
LEFT JOIN worker AS c ON a.production_worker = c.id
有关各种联接的详细介绍,请参阅:A Visual Explanation of SQL Joins
您需要 left join
而不是 inner join
SELECT
a.id,
a.task,
a.shop_req,
CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req,
CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks a
left join worker b ON a.shop_worker = b.id
left join worker c ON a.production_worker = c.id
已编辑*1
我是软件开发人员的实习生,所以我对 MySQL-数据库没有太多经验。
我想为任务写一个工单,它包含了工人的详细信息以及需要哪个工人。
我在数据库中有一个 table,其中包含工人的姓名和部门。
table worker
看起来像这样:
+---------+---------+----------+------------+
| id (PK) | surname | forename | department |
+---------+---------+----------+------------+
| 1 | bar | foo | shop |
+---------+---------+----------+------------+
| 2 | baz | foo | production |
...
而 table tasks
看起来像这样:
+---------+------------+----------+-------------+----------------+-------------------+----
| id (PK) | task | shop_req | shop_worker | production_req | production_worker | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 1 | do sth. | yes | 1 | yes | 2 | ...
+---------+------------+----------+-------------+----------------+-------------------+----
| 2 | do sth. | no | (NULL) | yes | 2 | ...
...
如何将它们连接在一起?
我试过这个SQL-代码:*1
ALTER TABLE tasks
ADD CONSTRAINTS FK_tasks_shop
FOREIGN KEY (shop_worker)
REFERENCES worker(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
ADD CONSTRAINTS FK_tasks_production
FOREIGN KEY (production_worker)
REFERENCES worker(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
当我使用以下 SQL-代码调用 table tasks
时:
SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
JOIN worker AS b ON a.shop_worker = b.id
JOIN worker AS c ON a.production_worker = c.id
结果是:
+----+------+----------+-------------+----------------+-------------------+----
| id | task | shop_req | shop_worker | production_req | production_worker | ...
+----+------+----------+-------------+----------------+-------------------+----
表示结果只有列名,没有行。
我希望得到以下结果:
+----+------------+----------+-------------+----------------+-------------------+----
| id | task | shop_req | shop_worker | production_req | production_worker | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 1 | do sth. | yes | bar, foo | yes | baz, foo | ...
+----+------------+----------+-------------+----------------+-------------------+----
| 2 | do sth. | no | (NULL) | yes | baz, foo | ...
...
这里有什么问题?我找不到错误。
有没有有效的方法调用SQL-代码?
非常感谢您的回答!
首先,您的查询缺少 tasks
的 AS a
别名,这会使查询失败。添加后,您应该返回一行,但是 ...
因为您想要包含 tasks
table 中的所有行,即使 shop_worker
或 production_worker
没有匹配的行,您也需要使用left join
而不是像这样:
SELECT a.id, a.task, a.shop_req, CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req, CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks AS a
LEFT JOIN worker AS b ON a.shop_worker = b.id
LEFT JOIN worker AS c ON a.production_worker = c.id
有关各种联接的详细介绍,请参阅:A Visual Explanation of SQL Joins
您需要 left join
而不是 inner join
SELECT
a.id,
a.task,
a.shop_req,
CONCAT(b.surname, ', ', b.forename) AS shop_worker,
a.production_req,
CONCAT(c.surname, ', ', c.forename) AS production_worker
FROM tasks a
left join worker b ON a.shop_worker = b.id
left join worker c ON a.production_worker = c.id