【问题标题】:MySQL best approach for db normalising, relationships and foreign keysMySQL 数据库规范化、关系和外键的最佳方法
【发布时间】:2013-08-13 00:41:40
【问题描述】:

首先有一个用户名/密码验证步骤,然后数据库具有以下结构

^ is primary key

* uses foreign key


1.StudentDetails table
===========================================================================  
 ID^| Username   | Password | Email       | Address * | Website |Comments
====+============+==========+=============+===========+=========+========== 
1   | xxxxxxxxxx | xxxxxxx  | xx@xxx.xxx  | 1         | http:// | text

2.Submissions table
===========================================================================================
ID^|Username*|SubmitDate|SelectedCourse*|Price*|Promotion*|SubmitComments|SubmitStatus*
===+=========+==========+===============+======+==========+==============+=================
1  |xxxxxxxxx|2013-7-12 |  int          | int  |  int     | text         | int


3.SubmitComplete table
==================================================
ID^| Username * | SelectionDate | SubmitStatus *  
====+============+===============+================
1   | xxxxxxxxxx |  2013-08-01   | int

现在我在输入地址时遇到问题,当我尝试输入学生详细信息时,它不会接受,直到有地址字段,如何最好地解决这个问题? 当我从 StudentDetails 中选择某些字段并从 Addresses 中选择某些字段时,地址不显示。

我是一个 mysql 菜鸟,所以我想要一些指导,看看规范化和结构是否正确完成,或者可以做得更好,这里是 fiddle 我无法让它正常工作,尽管架构的构建在我的机器上运行良好,但在我添加外键的行上不断出现错误。

小提琴控制台在第 2 行显示错误,但在我看来它实际上在第 76 行。 如果有什么我不清楚的,请告诉我。 谢谢

【问题讨论】:

  • 我会使用用户 id 作为提交和提交完成表中的外键,而不是用户 name。 (并在 student.username 上添加唯一约束)
  • @wildplasser 我不确定我是否正确理解你,但如果我这样做,那就是我所做的,你可以在小提琴 Submissions.Username 和 SubmitComplete.Username 中看到它都使用 StudentDetails.id 作为关键,我没有做的是唯一的约束。
  • 嗨,鲍勃,我为你准备了新的小提琴。我没有用值填充表格,只是创建了它们,但在底部你可以看到我的 cmets 到你的小提琴。你可以在这里找到小提琴sqlfiddle.com/#!2/c03dd
  • @Wirus 感谢您的帮助 cmets(像往常一样)我认为我的小提琴的问题没有首先索引键(noob 错误...lol Ooops)至于您的 cmets,地址 1、2 3不是不同的地址,它为更长的地址添加了字段,不同的国家有不同的地址结构。提交费用、价格、课程和促销是 4 个不同的实体,费用每年支付一次,不管有多少课程,可以添加新课程,其中价格可能会每年变化,促销折扣只影响课程价格而不影响提交费用,这就是我这样做的原因,这有意义吗?
  • 嗨,Bob,您必须考虑哪些属性属于哪个对象。课程有价格。在您的旧结构中,您将有许多记录一门课程,但不同年份。因此,您可以将价格列添加到课程表中。或者您可以创建包含 startDate、endDate、price 的 CourseDetails 表,并在 Course 中仅存储一些常见字段,如 courseName、courseDesc 等。另一方面,Course 的 Promos 可能很少,用户可以选择一个。所以恕我直言,它应该是提交的财产。但这只是一个简短的评论,因为我什至没有足够的时间思考你的答案

标签: mysql foreign-keys relational-database database-normalization


【解决方案1】:

好的,让我解释一下它会是怎样的。我用两个表格做了一个例子,你可以在下面看到。

然后您可以创建查询。

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| addresses      |
| students       |
+----------------+
2 rows in set (0.00 sec)

mysql> select * from students;
+----+----------+-----------+
| id | name     | last_name |
+----+----------+-----------+
|  1 | jhon     | smith     |
|  2 | anderson | neo       |
|  3 | trinity  | jackson   |
+----+----------+-----------+
3 rows in set (0.00 sec)

mysql> select * from addresses;
+----+-----------------+---------+
| id | address         | student |
+----+-----------------+---------+
|  1 | Av 1 2nd Street |       1 |
|  2 | Av 3 4 Street   |       2 |
|  3 | St 23 7 Av      |       3 |
+----+-----------------+---------+
3 rows in set (0.00 sec)

mysql> select s.name,s.last_name,a.address from students s join addresses a on a.student=s.id;
+----------+-----------+-----------------+
| name     | last_name | address         |
+----------+-----------+-----------------+
| jhon     | smith     | Av 1 2nd Street |
| anderson | neo       | Av 3 4 Street   |
| trinity  | jackson   | St 23 7 Av      |
+----------+-----------+-----------------+
3 rows in set (0.00 sec)

【讨论】:

  • 感谢您的勤奋,我最终得到了类似的解决方案SELECT sd.Username, sd.Email, sd.Website, ad.Address_1, ad.City, ad.Country FROM StudentDetails sd, Addresses ad WHERE sd.id = ad.id 不同之处在于您的地址表只有 1 列,而我的有 3 列是问题的一部分。现在我试图连接我的地址列(Address_1,Address_2,Address_3),如果它不为 NULL,但每当我这样做时,我在这里得到空查询CONCAT (ad.Address_1, ad.Address_2, ad.Address_3) AS fullAddress,
  • 在这种情况下,您应该尝试 CONCAT(IF(addr1,''),IF(addr2,''),IF(addr1,'')) AS full_address;
  • 用 IF 这样它给了我一个错误我尝试了 IFNULL 这没有给我错误,但没有给我他想要的结果,我想添加一个换行符,如果它在 addr1 之后不为空和 addr2 以便于阅读
  • 我以前不知道这一点,但在 mysql IF(expr1,expr2,expr3) IF 函数接受三个参数,并根据 expr1 是否为 TRUE 返回结果。如果 expr1 被评估为 TRUE,则函数返回 expr2。否则,返回 expr3。这样就解决了那个问题:)
  • 嗨,鲍勃,又是我 :) 恕我直言,将整个地址保存在一个字段中并不是一个好主意。你应该有地址(id,studentId,Country,Region,City,address,number),地址是街道。通过这种方式,您可以验证这些字段,按它们进行搜索等。然后您不需要此 concats、ifs 等,您只需将地址加入学生并获得一个。您可以添加订单列(或者只是假设您从加入中获得第一个),您可以添加 isDefault 标志,以便您可以使用默认地址预先填写一些表格。
【解决方案2】:

选项 1:
先输入地址数据,在StudentDetails中创建行时使用该id

选项 2:
更改字段 StudentDetails.Address 使其允许 NULL 值,输入 StudentDetails,然后输入地址,然后更新 StudentDetails.Address

【讨论】:

  • 感谢您的建议,我可以从 php 中做到这一点吗?你会说标准化正确完成了吗?你也可以看看我的小提琴,看看我做错了什么吗?谢谢
【解决方案3】:

最好使用数字格式的外键所以Username应该是StudentDetails表的id。

您可以输入您尝试运行的 SQL 查询吗?

【讨论】:

  • 这就是我所做的,你可以看看这里的小提琴是查询 select * from StudentDetails left join Addresses on StudentDetails.id = Addresses.id;但是,当您在任一侧指定某些字段时,仅显示一侧,否则我会收到错误
  • 我不明白你想做什么。地址是另一张桌子,不是吗?如果模型是正确的,但为什么要尝试加入两个表的 id?如果我是你,我会这样查询:SELECT * FROM StudentDetails LEFT JOIN Addresses on StudentDetails.id = Addresses.student_id;其中 student_id 是外键。
  • 我要做的是从 StudentDetails 表中选择用户名、电子邮件和网站,从 Addresses 表中选择 Address_1、城市和国家。查询会怎样?
猜你喜欢
  • 2018-04-03
  • 2012-01-11
  • 1970-01-01
  • 2013-09-01
  • 2011-10-15
  • 2016-06-30
  • 2012-08-10
  • 1970-01-01
  • 2016-03-21
相关资源
最近更新 更多