主键SQL教程–如何在数据库中定义主键
Every great story starts with an identity crisis. Luke, the great Jedi Master, begins unsure - "Who am I?" - and how could I be anyone important? It takes Yoda, the one with the Force, to teach him how to harness his powers.
每个伟大的故事都始于身份危机。 绝地大师大师卢克开始不确定- “我是谁?” -我怎么能成为重要人物? 拥有部队的尤达需要教他如何利用自己的力量。
Today, let me be your Yoda.
今天,让我成为你的尤达。
We'll start with how to choose a Primary Key, fight an identity crisis, and then finish with code samples for creating a Primary Key in a database.
我们将从如何选择主键,应对身份危机开始,然后结束于在数据库中创建主键的代码示例。
如何选择主键 (How to Choose a Primary Key)
You may think Luke is the only one with an identity crisis, but that's not true. When creating a database, everything is in an identity crisis. And that's exactly why we need primary keys: they resolve the crisis. They tell us how to find everyone.
您可能会认为卢克是唯一遭受身份危机的人,但这不是事实。 创建数据库时,一切都陷入身份危机。 这就是我们需要主键的原因:它们可以解决危机。 他们告诉我们如何找到每个人。
Imagine you're the government, and you want to identify each one of your citizens digitally. So, you create this database with everything about them:
假设您是政府,并且您希望以数字方式识别每个公民。 因此,您将使用有关它们的所有内容来创建此数据库:
First Name
Last Name
Passport Number
You choose the passport Number as the Primary Key - the identity for everyone. You figure that's all you need since the passport has the address and everything else. You know passport numbers are unique, so you feel good and implement this system.
您选择护照号码作为主密钥-每个人的身份。 您认为这就是您所需要的,因为护照上有地址和其他所有内容。 您知道护照号码是唯一的,因此您会感觉良好并实施此系统。
Then, a few years later, you find out an ugly truth: the entire country is facing an identity crisis.
然后,几年后,您发现了一个丑陋的事实:整个国家都面临着身份危机。
Whenever someone's passport expires, they get a new one. Their identity changes. Other systems keep using the old passport numbers, so they now point to ghost people.
每当某人的护照过期时,他们都会换一张新护照。 他们的身份改变了。 其他系统继续使用旧的护照号码,因此现在它们指向虚假人员。
Uniqueness isn't enough. The value must not change throughout the row's lifetime.
唯一性还不够。 该值在整个行的生存期内都不得更改。
And then, you find there are some people who don't even have passports. You can't enter them into your system, since Primary Keys can't be NULL
. How can you identify someone with a NULL
key?
然后,您会发现有些人甚至没有护照。 您不能将它们输入到系统中,因为主键不能为NULL
。 如何识别使用NULL
键的人?
Every row must have an identifier. NULLs not allowed.
每行必须有一个标识符。 不允许为NULL。
The next iteration means finding an identifier that doesn't change over time, and one that everyone has. In India, this is turning out to be the Adhaar Card. In the USA, the Social Security Number.
下一轮迭代意味着找到一个不会随时间变化的标识符,而每个人都会拥有。 在印度,这真是Adhaar卡。 在美国,社会安全号码。
If you're creating a database, make those your primary keys.
如果要创建数据库,请以这些为主键。
Sometimes, you don't have any such key. Consider a country that doesn't have a Social Security Number yet, and they want to create a digital record of every citizen. They could create a new SSN, or they could just leverage the power of databases, and use a surrogate key.
有时,您没有任何此类密钥。 考虑一个尚无社会保险号的国家,他们想创建每个公民的数字记录。 他们可以创建新的SSN,也可以仅利用数据库的功能并使用代理密钥。
A surrogate key has no real world equivalent. It's just a number inside a database. So, you have this table in the new country:
代理密钥没有现实世界的等效项。 它只是数据库中的一个数字。 因此,您在新国家/地区拥有此表格:
userID
First Name
Last Name
Passport Number
Passport Numbers are unique. Whenever you want to get the identifier for a user, you can get it via the Passport Number.
护照号码是唯一的。 每当您想要获取用户的标识符时,都可以通过护照号码获取。
The userID never changes. The Passport Number can change - but it's always unique, so you always get the right user. The userID is a surrogate for a non-existing Social Security Number in this country.
userID永远不会更改。 护照号码可以更改-但是它始终是唯一的,因此您始终可以找到合适的用户。 userID是该国家/地区不存在的社会保险号的替代 。
Fun fact: The Passport Number here is also a Candidate Key. It could've been the Primary Key, if it never changed. This is a business logic distinction.
有趣的事实:这里的护照号码也是一个候选密钥。 如果它从未更改,它可能是主键。 这是业务逻辑上的区别。
The main takeaway is this: Whenever you're choosing a Primary Key, think of an identity crisis. Is it possible that someone might change their identifier in the future? Can we get into a state with multiple people having the same identifier?
主要收获是: 每当您选择主键时,请考虑一下身份危机 。 将来有人可能会更改其标识符吗? 我们可以进入多个人使用相同标识符的状态吗?
I use people as an example, because it makes identity clearer - we know every person is supposed to have an identity. Transfer this thinking to your databases. Everything has an identity, which is exactly why you need Primary Keys.
我以人为例,因为它使身份更清晰-我们知道每个人都应该有一个身份。 将此思想转移到您的数据库。 一切都有一个身份,这就是为什么您需要主键的原因。
Note: Sometimes, it's possible, and desirable to use multiple columns together as the Primary Key. This is a Composite Key.
注意:有时,并且有可能并希望同时使用多列作为主键。 这是一个组合键。
Now let's try defining Primary Keys with real code examples. There's two things to do here: first, you'll identify the Primary Key. Then, you'll learn the syntax for defining it in a database.
现在,让我们尝试使用真实的代码示例来定义主键。 这里有两件事要做:首先,您将识别主键。 然后,您将学习在数据库中定义它的语法。
一个真实的例子 (A real world example)
Let's say you run a shipping startup, much like Flexport. You have packages that need to get from one place to another, and ships that transport them. Further, you have customers who are ordering these packages.
假设您经营一家货运公司,就像Flexport。 您有需要从一个地方到达另一个地方的包裹,并需要将它们运输的船。 此外,您有正在订购这些软件包的客户。
You figure you'll need one table for the customers, one for the packages, and one for transportation, showing which package is where right now.
您会发现您需要一张桌子供客户使用,一张需要包装,另外一张需要运输,以显示当前哪个包装。
Think through what columns you'll need, and what should be the Primary Key. If you were an engineer at Flexport, this is an actual question you would have to figure out. Nothing is given, everything is discovered in the real world.
考虑一下您将需要哪些列,什么应该是主键。 如果您是Flexport的工程师,这是一个必须解决的实际问题。 一无所有,一切都在现实世界中发现。
Given this information, I'd design these tables like so:
有了这些信息,我将像这样设计这些表:
Customers: first_name, last_name, email, address (for deliveries to their location)
Packages: weight, content
Transportation: <package_primary_key>, Port, time
We're missing the primary keys. Think about them before reading further.
我们缺少主键。 在进一步阅读之前,请先考虑一下它们。
For the package, I'll choose a surrogate PackageID. I could have tried to list all the attributes of the package: weight, volume, density, age. They would uniquely identify the package, but this is very hard to do in practice. People don't care about this, they just care about the package getting from one place to another.
对于包,我将选择代理 PackageID。 我本可以尝试列出包装的所有属性:重量,体积,密度,年龄。 他们会唯一标识包装,但这在实践中很难做到。 人们并不关心这一点,他们只是关心包裹从一个地方到另一个地方的运输。
So, it makes sense to create a random number and use that as the ID. This is exactly why you see FedEx, UPS, and every delivery service use barcodes and IDs. These are surrogate keys generated to track packages.
因此,创建一个随机数并将其用作ID很有意义。 这就是为什么您看到FedEx,UPS和每个送货服务都使用条形码和ID的原因。 这些是生成的用于跟踪包裹的代理密钥。
For the customer, I'll choose a surrogate CustomerID. Here, again, I had an option to choose, say, the Social Security Number of my customers. But, customers don't want to share this with me just so I can ship them something. Thus, we generate a key internally, don't tell our customers about this key, and continue calling them CustomerNo. 345681.
对于客户,我将选择一个替代客户ID 。 同样,在这里,我可以选择客户的社会保险号。 但是,客户不想仅与我分享此信息,以便我可以向他们发货。 因此,我们在内部生成密钥,不要告诉客户此密钥,而是继续称其为CustomerNo。 345681。
Fun Story: I know a few companies where they exposed this CustomerNo, and the customers insisted they get No. 1. It was pretty hilarious - the engineers actually had to change their front-end code to:
if (cust == 345681) print(1);
有趣的故事:我知道一些公司在这里公开此CustomerNo,并且客户坚持要获得No.1。这非常好笑-工程师实际上不得不将其前端代码更改为:
if (cust == 345681) print(1);
For Transportation, I'll choose a composite PackageID+Port+time. This is a bit more interesting. I could have created a surrogate here as well, and it would work just as well.
对于运输,我将选择一个复合 PackageID + Port + time。 这有点有趣。 我也可以在这里创建一个代理 ,它也可以正常工作。
But, here lies the magic of indexing. The Primary Keys get an index automatically, which means searching is a lot more efficient over Primary Keys.
但是,这就是建立索引的魔力。 主键会自动获取索引,这意味着搜索比主键要有效得多。
When you're searching through this database, most queries will be of the form "where is this package?". In other words, given this PackageID, tell me the Port and Time it is at right now. I would need an extra index over PackageID if I don't have it as part of my Primary Key.
当您搜索该数据库时,大多数查询将采用“此软件包在哪里?”的形式。 换句话说,给定这个PackageID,告诉我现在的端口和时间。 如果我没有将其作为主键的一部分,则需要在PackageID上有一个额外的索引。
Does this sound good? Final step, let's define these 3 tables in SQL. The syntax varies slightly with the database you're using.
听起来不错吗? 最后一步,让我们在SQL中定义这3个表。 语法随所使用的数据库而略有不同。
在MySQL中定义主键 (Defining Primary Keys in MySQL)
CREATE TABLE customers
( customerID INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,last_name VARCHAR(30) NOT NULL,first_name VARCHAR(25) NOT NULL,email VARCHAR(50) NOT NULL,address VARCHAR(300)
);
CREATE TABLE packages
( packageID INT(15) NOT NULL AUTO_INCREMENT,weight DECIMAL (10, 2) NOT NULL,content VARCHAR(50),CONSTRAINT packages_pk PRIMARY KEY (packageID) # An alternative way to above,# when you want to name the constraint as well.
);
CREATE TABLE transportation
( package INT(15) NOT NULL,port INT(15) NOT NULL,time DATE NOT NULL,PRIMARY KEY (package, port, time),FOREIGN KEY packageREFERENCES packages(packageID)ON DELETE RESTRICT # It's good practice to define what should happen on deletion. In this case, I don't want things to get deleted.);
在PostgreSQL中定义主键 (Defining Primary Keys in PostgreSQL)
CREATE TABLE customers
( customerID SERIAL NOT NULL PRIMARY KEY, # In PostgreSQL SERIAL is same as AUTO_INCREMENT - it adds 1 to every new row.last_name VARCHAR(30) NOT NULL,first_name VARCHAR(25) NOT NULL,address TEXT,email VARCHAR(50) NOT NULL
);
CREATE TABLE packages
( packageID SERIAL NOT NULL,weight NUMERIC NOT NULL,content TEXT,CONSTRAINT packages_pk PRIMARY KEY (packageID) # In PostgreSQL, this alternative way works too.
);
CREATE TABLE transportation
( package INTEGER NOT NULL,port INT(15) NOT NULL,time DATE NOT NULL,PRIMARY KEY (package, port, time),FOREIGN KEY packageREFERENCES packages(packageID)ON DELETE RESTRICT # It's good practice to define what should happen on deletion. In this case, I don't want things to get deleted.);
It's not very different, is it? Once you get the basics down, you can apply it to almost any database with just a quick look at the documentation. The key is knowing what to look for!
不是很不同,是吗? 掌握基础知识之后,只需快速浏览一下文档,便可以将其应用于几乎所有数据库。 关键是知道要寻找什么!
Good luck, young padawan.
祝您好运,年轻的帕达万。
Enjoyed this? You might also like Things I Learned From a Senior Software Engineer
喜欢这个吗? 您可能还喜欢我从高级软件工程师那里学到的东西
翻译自: https://www.freecodecamp.org/news/primary-key-sql-tutorial-how-to-define-a-primary-key-in-a-database/
相关文章:

算法(2)KMP算法
1.0 问题描述 实现KMP算法查找字符串。 2.0 问题分析 “KMP算法”是对字符串查找“简单算法”的优化。字符串查找“简单算法”是源字符串每个字符分别使用匹配串进行匹配,一旦失配,模式串下标归0,源字符串下标加1。可以很容易计算字符串查…

告别无止境的增删改查:Java代码生成器
对于一个比较大的业务系统,我们总是无止境的增加,删除,修改,粘贴,复制,想想总让人产生一种抗拒的心里。那有什么办法可以在正常的开发进度下自动生成一些类,配置文件,或者接口呢&…

Maven国内源设置 - OSChina国内源失效了,别更新了
Maven国内源设置 - OSChina国内源失效了,别更新了 原文:http://blog.csdn.net/chwshuang/article/details/52198932 最近在写一个Spring4.x SpringMVCMybatis零配置的文章,使用的源配的是公司的私有仓库,但是为了让其他人能够通过…
如何使用Next.js创建动态的Rick and Morty Wiki Web App
Building web apps with dynamic APIs and server side rendering are a way to give people a great experience both with content and speed. How can we use Next.js to easily build those apps?使用动态API和服务器端渲染来构建Web应用程序是一种使人们在内容和速度上都…

安装部署Spark 1.x Standalone模式集群
Configuration spark-env.sh HADOOP_CONF_DIR/opt/data02/hadoop-2.6.0-cdh5.4.0/etc/hadoop JAVA_HOME/opt/modules/jdk1.7.0_67 SCALA_HOME/opt/modules/scala-2.10.4 ####################################################### #主节点 …

算法(3)简单四则运算
1.0 问题描述 实现10以内四则运算(只包含数字,*/和小括号) 2.0 问题分析 四则运算使用“后缀表达式”算法来计算,后缀表达式可以无需考虑运算符优先级,直接从左至右依次计算。问题分解成2部分,一是将“中…

调用短信接口,先var_dump()看数据类型是object需要json_decode(json_encode( $resp),true)转换成array...
返回的数据.先看类型,如果是object类型 先json_encode, 再json_decode,加true 转换成数组 $resp $c->execute($req); var_dump($resp); object(stdClass)#12 (2) { ["result"]> object(stdClass)#13 (3) { ["err_code"]> string(1) "0"…

nlp文本数据增强_如何使用Texthero为您的NLP项目准备基于文本的数据集
nlp文本数据增强Natural Language Processing (NLP) is one of the most important fields of study and research in today’s world. It has many applications in the business sector such as chatbots, sentiment analysis, and document classification.Preprocessing an…

R语言-基础解析
二、操作基础%%取余%/%整数除法(1)eigen(...)求解方阵的特征值和特征向量(2)solve(D,A)求解DXA(3)data<-list(...)取里面的对象data[["列名称"]];data[[下标]];data$列名称(4)unlist(列表对象)把列表对象转化为向量对象(5)names(数据框)读取…

算法(4)数据结构:堆
1.0 问题描述 实现数据结构:堆。 2.0 问题分析 堆一般使用数组来表示,其中某个节点下标i的两个子节点的下标为 2i1 和 2i2。堆是一棵完全二叉树。堆有3种基本操作:创建,插入,删除。这3种操作都需要通过“调整堆”的…

cookie 和session 的区别详解
转自 https://www.cnblogs.com/shiyangxt/archive/2008/10/07/1305506.html 这些都是基础知识,不过有必要做深入了解。先简单介绍一下。 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会…

如何设置Java Spring Boot JWT授权和认证
In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring. 在过去的一个月中,我有机会为辅助项目实现JWT auth。 我以前曾在Ruby on Rails中使用…

算法(5)哈希表
1.0 问题描述 实现数据结构:哈希表。 2.0 问题分析 哈希表可以看作我们经常使用的字典(swift)或对象(js),可以让一个key&value对一一对应,可以快速根据key找到value。哈希表内部使用数组…

《面向对象程序设计》c++第五次作业___calculator plus plus
c第五次作业 Calculator plusplus 代码传送门 PS:这次作业仍然orz感谢一位同学与一位学长的windows帮助,同时再次吐槽作业对Mac系统用户的不友好。(没朋友千万别用Mac!!!) 还有想吐槽作业对规范的要求大大超…

联合体union和大小端(big-endian、little-endian)
1.联合体union的基本特性——和struct的同与不同union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。在成员完全相同的情况下,struct比…

前端面试的作品示例_如何回答任何技术面试问题-包括示例
前端面试的作品示例Technical interviews can be extremely daunting. From the beginning of each question to the end, its important to know what to expect, and to be aware of the areas you might be asked about. 技术面试可能会非常艰巨。 从每个问题的开始到结束&a…

$(shell expr $(MAKE_VERSION) \= 3.81) 这里“\”的解释
android/build/core/main.mk $(shell expr $(MAKE_VERSION) \> 3.81) 为什么要加多一个“\”,因为">"会被shell解析为重定向符号,所以需要转义或用引号包围 所以,也可以这样写$(shell expr $(MAKE_VERSION) “>” 3.81)转载于:https:…

iOS应用模块化的思考及落地方案(一)模块的划分及模块化工作流程
1.0 什么是模块化 很多关于重构及设计模式的介绍中,经常提到的几个词语是复用及解耦。 模块化之所以被提出,也更多是为了解决这几个问题。 复用可以减少重复造轮子的情况,很容易理解的是,我们经常使用的github上的第三方框架&a…

Swiper 用法
部分常用API ininialSlide: 2, //起始图片切换的索引位置(起始从0开始,默认为0) autoplay: 3000, //设置自动切换时间,单位毫秒 speed: 1000, //设置滑动速度 continuous: true, //无限循环的图片切换效果 disableScroll: true, /…
node/js 漏洞_6个可用于检查Node.js中漏洞的工具
node/js 漏洞Vulnerabilities can exist in all products. The larger your software grows, the greater the potential for vulnerabilities. 所有产品中都可能存在漏洞。 您的软件增长得越大,潜在的漏洞就越大。 Vulnerabilities create opportunities for expl…

发现一个浏览器很奇怪的问题
浏览器有8个请求状态为pending时,在另一个tab中,请求就发布出去了,一直是stalled。直到pending状态变成了cancled状态。 试了360浏览器(谷歌内核)和chrome浏览器,都是这样。 具体的原因待深究 参考…

wamp配置虚拟主机
因为wampserver的php版本一直是5.x版本;因此转投xmapp用了一段时间; 意外发现wampserver3更新了;php也终于更新到7了; 果断还是决定回到wampserver的怀抱; 然后有意外的发现了wampserver3有了新功能;可以方…

iOS应用模块化的思考及落地方案(二)模块化自动构建工具的使用
1.0 iOS模块化中的问题 前文已经介绍了模块化的流程及一些常见的问题,我们在这里再次总结一下。 在工作中,当我们开始一个新项目的时候,最先考虑的就是模块化工作。 模块化工作的想法是很美好的,可是执行过程中会遇到很多的问题…

aws fargate_我如何在AWS Fargate上部署#100DaysOfCloud Twitter Bot
aws fargateAfter passing my last certification, I asked myself how much time I spent studying cloud computing.通过上一份认证后,我问自己自己花了多少时间研究云计算。 More than 100 days!超过100天! It also made me realize two things:这也…

think in Java 第五章之垃圾回收类型
1.引用计数: 每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1,当引用离开作用域或被置为null时,引用计数减1. 缺陷:在对象循环引用时,存在“对象应该被回收,引用计数…
Yii 错误页面处理
【错误页面处理】 訪问一个错误的控制器 訪问一个错误的方法 有些控制器和方法禁止訪问 以上訪问会提示错误信息 404 403 以上错误信息是不方便给外边用户看到的。 1. 安全隐患 2. 用户体验不好 错误信息在site/error这个地方定义的。如今我们要自己定义错误页面来显示我们的错…

设置RGBColor
#define kUIColorFromRGB(rgbValue) [UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

自学成才翁_作为一名自学成才的开发者从“我的旅程”中吸取的教训
自学成才翁The path of the self-taught developer is tough and filled with uncertainty. There is no straight line from newbie to career programmer. Because of this, I believe all self-taught developers have a unique story to tell.自学成才的开发者之路艰难而充…

67)vector的begin() end() 和 front() back()的区别 rbegin() rend()
1) 2)v1.begin() 和v1.end() 是作为迭代器v1的 第一个位置 和 最后一个元素的下一个位置。 v1.front() 是v1这个动态数组的第一个元素的值 v1.back()是v1的最后一个元素的值。 3) 4)正向和反向的使…

倒置函数reverse的用法
倒置字符串函数reverse:用于倒置字符串s中的各个字符的位置,如原来字符串中如果初始值为123456,则通过reverse函数可将其倒置为654321,程序如下:#include<stdio.h>#include<string.h>void reverse(char s[…