您好我是数据库的初学者,因此我想问您应该使用哪些属性作为主键来避免错误:
CREATE TABLE customer(
name
first_lastname
street
ZIP_code
mobile_phone
telephone
email
gender
birthdate
nationality);
我可以选择将idcustomer添加为auto_increment,但我不确定这是个好主意。
答案 0 :(得分:4)
我正在考虑将idcustomer添加为auto_increment,但我不确定这是一个好主意。
这确实是一个好主意。
您的其他列(属性)不一定具有唯一值。换句话说,它们不适合用作自然主键。什么样的价值可以作为一个自然的主键?可能是员工编号。 产品序列号可能有效。纳税人身份证号码(社会安全号码)不起作用:令人惊讶的是,有多少人误用了重复的号码。选择真实项目作为主键的唯一性标准是如此之高,以至于大多数数据库设计者甚至都没有尝试过。
因此,创建一个保证唯一的主键通常是很好的设计。这种密钥的术语是代理主键。大多数DBMS系统(包括MySQL)都为此提供自动递增数字。
您可以选择两种约定之一来命名id
值。一个是称之为id
。另一种是将其称为customer_id
(添加了_id
的表名)。当您开始在其他表中使用这些值来建立关系时,第二个将帮助您保持正确。
例如,您可能有一个销售表。该表可能包含以下列:
sales_id autoincrementing pk
customer_id the id of the customer to whom the sale was made. (foreign key)
item_sold description of the item
list_price
discount
net_price
你明白了。阅读primary keys和foreign keys。在“逻辑数据库设计”的术语中,您可以阅读实体(客户,销售)和关系。每个表都有自己的一系列自动递增值。
然后,您可以使用这样的查询来查找每个客户的销售情况。
SELECT customer.name, customer.first_lastname,
COUNT(sales.sales_id) number_of_sales,
SUM(sales.net_price) revenue
FROM customer
JOIN sales ON customer.customer_id = sales.customer_id
GROUP BY customer.customer_id, customer.name, customer.first_lastname
此处sales
实体与customer
实体具有多对一的关系。这是通过在每个customer_id
行中指向客户的sales
属性来实现的。
将id作为每个表中的第一列也是一种惯例。
约定很好:它们可以帮助下一个人查看您的应用程序。它们也有助于你未来的自我。
注意:我的销售表只是一个示例,用于说明如何自动增加id值。我并不认为它是真实世界销售表的良好布局:它不是。
答案 1 :(得分:2)
PRIMARY KEY有几个理想的属性(其中一些很明显,但我们会枚举它们)
我们可以持有意见,并讨论每个属性,含义和好处,以及没有这些属性的主键的缺点。但是很多人最终会对什么是最重要的,以及什么都不重要的事情发表意见。)
我有理由认为这些属性中的每一个都是理想的。我承认其他人不同意。
如果此列表有效,则代理主键可以适合所有这些。
在MySQL中,实现代理主键的一种可能方法是在表中添加一个额外的列:
p4 submit
请注意,使用AUTO_INCREMENT 不是一项要求。这是许多有用且易于使用的功能。 (有一些关于AUTO_INCREMENT的细节使得它在PRIMARY KEY方面不是一个完美的功能。)
重要强>
我不断言使用代理主键是正确的方式,或唯一的方法。
代理主键不是成功的数据库实施项目的要求。许多成功的项目都是使用自然键实现的。
但是我会注意到(在结束时)一些坚定的自然键信徒在事件发生时(在项目后期,新发现的要求)被严重烧伤,所选择的自然键变得不满足一个(或更多)我列出的“理想属性”。
答案 2 :(得分:1)
令人惊讶的是,到目前为止,没有一个答案询问您的业务需求。您是否了解您的业务流程,与客户进行的交互以及如何在业务领域中识别客户?标识属性 - 在电子商务应用程序中,它可能是一个登录名 - 例如 - 通常应该是您表中的一个键。除非您了解该密钥的用途,否则添加自动增量不是正确的做法。
答案 3 :(得分:0)
主键是唯一标识表中行的列或一组列。考虑到这一点,您可以将唯一标识customer
行的列作为主键。您可以使用电话号码或名字,姓氏和电话号码的组合作为主键。但更容易接受的方法是添加一个额外的列,可能是您想象的idcustomer
或customer_id
或id
,这对于每个客户来说都是唯一的,并使其成为首要的关键;制作这个整数列auto_increment
是一个好主意。
答案 4 :(得分:0)
最安全的方法是在每个表上创建一个名为id
的PK列。不要成为英雄,只要去找一个没有签名的bigint。 PK溢出,但不太可能,不是你想要的问题。
您可以使用:
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
或者使用SERIAL
关键字替换中间位,这是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
的别名
请记住,如果您使用基于语句的复制,AUTO_INCREMENT可能会导致问题。基于语句的复制是5.7.6之前的默认复制。
使用合成键将您正在建模的对象的特征与该对象的唯一标识符分离,如果您需要更改架构,这将非常方便。改变MySQL PK是很昂贵的。它还保证您将拥有一个唯一的非空列,以便使用外键进行引用。此外,一些ORM期望id
PK列 - 如果您涉及到这类事情。
使用MySQL,您可以创建一个复合聚簇索引,它是一个具有多个列的主键。如果您确定该表永远不会变得巨大,并且您将定期访问具有指定该键中最左侧列的子集的复杂过滤器,那么这可能是一种优化。我不会使用这种方法。
InnoDB表需要主键。即使您没有显式创建数据库,数据库也会隐式选择它找到的第一个UNIQUE列。如果没有,它将创建一个名为GEN_CLUST_INDEX的隐藏列。