
目录
上期我们讲述了 not null 和 unique 约束,而本期的第一个约束就是这俩的结合体,也成为主键约束。
主键约束,说白了就是 not null + unique,主键也是在插入数据的时候先进行查询,而 MySQL 则会对 unique,primary key 这样的列自动的添加索引(后续介绍),来提高查询的效率。
● 在实际开发中,大部分的表,一般都会带有一个主键,主键往往是一个整数表示的 id。
create table student (
id int primary key,
name varchar(10)
);
只要你给改列设置了主键,意味着后续插入的数据,既不能重复,也不能为空!
● 在 MySQL 中,一个表中只能有一个主键,不能有多个。
create table student (
id int primary key,
name varchar(10) primary ke
);
-- ERROR 1068 (42000): Multiple primary key defined
● 虽然主键不能有多个,但支持将多个列放到一起,共同作为主键,称为联合主键。
create table student (
id int,
name varchar(10),
primary key (id, name)
);
desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(10) | NO | PRI | NULL | |
+-------+-------------+------+-----+---------+-------+
-- 2 rows in set (0.00 sec)
这样我们就能发现 Key 这一列有两个 PRI 了,PRI 是主键的简写,表示是主键字段,同时也能看到 Null 这一列为 NO,所以主键包含了 not null 和 unique 的特性。
● 主键还有一个非常常用的用法,使用 MySQL 自带的自增主键作为主键的值。
create table student (
id int primary key auto_increment,
name varchar(10)
);
这里我们就来插入数据试一试:
insert into student value
(88, '李四'),
(12, '张三');
这里仍然可以插入成功,由此能发现设置了自增主键仍然能自定义值,那么下面如果不自定义 id 的值呢?会自动生成多少呢?
insert into student(name) values('王五');
-- Query OK, 1 row affected (0.00 sec)
select * from student;
+----+--------+
| id | name |
+----+--------+
| 12 | 张三 |
| 88 | 李四 |
| 89 | 王五 |
+----+--------+
-- 3 rows in set (0.00 sec)
注意:这里可以看到,我们插入是 李四,张三,但是查询却是 张三在前李四在后,所以 MySQL 并未保证插入顺序和取出是顺序是一致的!
再者这里可以发现,自增主键插入数据对应字段不给值时,使用最大值+1。那如果我把王五删了,再次插入一条数据,自增主键会是多少呢?
delete from student where name = '王五';
-- Query OK, 1 row affected (0.00 sec)
insert into student(name) values('赵六');
-- Query OK, 1 row affected (0.00 sec)
select * from student;
+----+--------+
| id | name |
+----+--------+
| 12 | 张三 |
| 88 | 李四 |
| 90 | 赵六 |
+----+--------+
-- 3 rows in set (0.00 sec)
看到没!并不是按照当前列的最大值来自增主键的,你可以理解为 MySQL 有个记录主键最大值的玩意,是按照这个之前主键最大值自增的!删除了数据,不影响主键的最大值!
我们再来看一个操作:
insert into student values(null, '孙七');
这个操作并不是插入 null 数据,而是交给数据库使用自增主键!
这里又有一个疑问了,如果数据量太大,一个服务器存不下那么多数据怎么办?那就要采用分库分表的操作了,多台服务器来存储了,本质上就是把一张大表,分成多张小表,每个服务器分别只存一部分大大数据,这就可以理解成分布式处理了,
问题来了,上述这样的情况,还能使用自增主键吗?
这里涉及到一个 "分布式系统中唯一 id 生成算法" ,也就是全局唯一 id,常见的即:
实现公式:时间戳+主机编号+随机因子 => 全局唯一的 id。
当然感兴趣的可以下来进一步了解下,这里就不过多阐述了。
外键约束,说白了就是两个表之间相互约束。
注意:外键是用于关联其他表的主键或唯一键!
foreign key (字段名) references 主表(列)
这里我们举个例子,在学校里,有很多个班级,每个班级里有很多学生,也就是一个学生对应一个班级,一个班级对应多个学生,假设某某学校,只有三个 java 班级,分别是 java1班,java2班,java3班,每个班级又有若干个学生,现在开学了,学生去学校报道, 报道的时候呢会登记你的班级,志愿者一问,同学你哪个班的呀?我说:我 java2 班的,于是顺利登记成功,后面又来了一个同学,同样的问题,同学你哪个班的呀?我 java6班,志愿者一查询,咱学校没有 java6班呀,于是那个同学就被老师带走调查了...
上述只是一个故事,可以把我们自己想象成一条数据,当然登记信息肯定不仅仅是登记班级,还有有 学号 姓名 性别 身份证 班级号... 而这里我们的班级号不是随便哪个都可以的,是有固定的几个班级号,如果这几个班级号中没有你报的班级号,那么你的信息,就录不上去,也就是一个错误的信息。假设这几个班级号放在一起,对应一张班级表,咱们登记登记的信息,对应学生表, 那么就是两张表之间指定字段的约束。
有了上述铺垫,我们就来用代码来理解一下:
● 首先创建一张班级表 classes,id 为主键:
create table classes (
id int primary key,
name varchar(10)
);
这样 classes 班级表就建好了,这里有个问题,为什么 id 要作为主键呢?
答:首先这里的 id 对应班级号,name 是班级名称,而外键是用于关联其他表的主键或唯一键,所以说这里的 id 字段,要不是主键,要不是唯一键。
未来学生表会有一个字段拥有外键属性,来关联这个 classes 的 id 字段!!!
● 创建学生表 student 指定 classId 为外键,关联 classes 表中 id 字段
create table student (
id int,
name varchar(10),
sex varchar(1),
classId int,
foreign key (classId) references classes(id)
);
这段 sql 语句最后一条,foreign key (classId) references classes(id),这条语句表示,将创建的 student 表中 classId 字段作为外键,于 classes 表中 id 字段关联!
这两张表是创建好了,现在得创建数据了,为 classes 表中创建三个班级数据:
insert into classes value
(1, 'java1班'),
(2, 'java2班'),
(3, 'java3班');
这样就能表示有存在了三个班级,分别是 1班,2班,3班,如果接下来我去登记信息,录入的班级在这三个班之中,那就毫无问题:
insert into student values (230115, '篮球哥', '男', 2);
-- Query OK, 1 row affected (0.00 sec)
这里是不是就如同我们上面举例说明的这样,我是 java2 班的,而 classId 录入了一个 2,关联 classes 的 id 字段 2,对应的就是 java2 班。
那如果后来的同学,录入一个 java6 班呢?
insert into student values (230205, '小王', '男', 6);
-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`demo`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `classes` (`id`))
那么此处的外键约束的含义,要求了 student 里的 classId 务必要在 classes 表的 id 列中存在!
相信看到这,大家都能明白外键约束的作用了,student 表中的数据,要依赖 classes 表的数据,而 classes 表的数据要对 student 表产生约束力,就像 父亲 对 孩子 有约束力。此处起到约束作用的表我们称为 "父表",被约束的表我们称为 "子表"。
看到这里啊,说白了就是 父表 对 子表 起到了约束作用,限制了约束的字段的取值.
这里我不禁想到一句话,当你在凝视深渊的时候,深渊也在凝视你!
我们表面上看确实是 父表 对 子表 起到约束,但反过来其实 子表 也限制着 父表!
这里我们尝试删除父表中 id 为 2 的数据,也就是删除 java1班:
delete from classes where id = 2;
-- ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`demo`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `classes` (`id`))
发现报错了,其实我们想也能想到,如果真能删除,那子表中 classesId = 2 的那一条数据不就尴尬了吗?那这外键约束建了又像没有建一样,所以就僵住了,显然是不允许这样的情况发生的!
当然 classes 表中 id 为 1 的数据可以删除,因为 子表 并不存在 classId 为 1 的数据嘛:
delete from classes where id = 1;
-- Query OK, 1 row affected (0.00 sec)
问题:可以先建子表再建父表吗?
显然是不行的呀,当你建子表指定外键约束的时候,你父表都没有,怎么建约束?
表的设计算是一个比较抽象的概念,有了一定经验后,会更好理解,结合后期的项目设计,再来理解表设计,可能会更好,这里就简单介绍下常见设计。
比如说我们每个人都有的身份证,每个身份证id,就对应一个人,这就是一对一关系。
这种一对一关系可以如何创建表呢?
● 第一种方案
create table person (
id int primary key,
name varchar(10),
address varchar(50),
sex varchar(1)
);
把身份证id和姓名直接放在一张表里.
● 第二种方案
create table person (
id int primary key,
name varchar(10)
);
create table account (
accountId int primary key,
personName varchar(10),
address varchar(50),
sex varchar(1),
id int,
foreign key (id) references person(id)
);
第二种方案则是身份证号和姓名放在不同的表里,相互关联。
这个例子很像我们之前说过的,一个班级有多个学生,一个学生对应一个班级,这里就不在赘述。
比如说学校的一门课程,可以被多名学生选修,而一名学生可以选修多门课程,这就是多对多的关系:

这里我们只需要让 student 表 studentId 字段 约束 student_course 表的 studentId 字段,以及 course 表 courseId 字段约束 student_course 表的 courseId 字段即可。
下期预告:【MySQL】聚合查询
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin
我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi
我使用脚手架和Rails3创建了2个模型。模型是位置和作业,每个作业都有一个位置。我在脚手架生成代码中创建了所需的引用调用,但是当我查看创建新作业的View时,我看到的只是一个文本框,我应该在其中添加location_id。我怎样才能让它变成下拉菜单以获得更好的用户体验? 最佳答案 想象一下,您有每个位置的titleAPI:http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select 关于r
我正在尝试绕过rails配置这个极其复杂的迷宫。到目前为止,我设法在ubuntu上设置了rvm(出于某种原因,ruby在ubuntu存储库中已经过时了)。我设法建立了一个Rails项目。我希望我的测试项目使用mysql而不是mysqlite。当我尝试“rakedb:migrate”时,出现错误:“!!!缺少mysql2gem。将其添加到您的Gemfile:gem'mysql2'”当我尝试“geminstallmysql”时,出现错误,告诉我需要为安装命令提供参数。但是,参数列表很大,我不知道该选择哪些。如何通过在ubuntu上运行的rvm和mysql获取rails3?谢谢。
文章目录前言约束硬约束的轨迹优化Corridor-BasedTrajectoryOptimizationBezierCurveOptimizationOtherOptions软约束的轨迹优化Distance-BasedTrajectoryOptimization优化方法前言可以看看我的这几篇Blog1,Blog2,Blog3。上次基于MinimumSnap的轨迹生成,有许多优点,比如:轨迹让机器人可以在某个时间点抵达某个航点。任何一个时刻,都能数学上求出期望的机器人的位置、速度、加速度、导数。MinimumSnap可以把问题转换为凸优化问题。缺点:MnimumSnap可以控制轨迹一定经过中间的
目录1、yum安装mysql修改密码(1)在mysql里面修改(2)第二种方式,利用mysqladmin修改密码2、没有密码,登录mysql修改密码3、mysql的安全设置1、yum安装mysql在CentOS中默认安装有MariaDB(MySQL的一个分支),安装完成之后可以直接覆盖MariaDB。rpm-qa|grepmariadb查询是否安装了mariadbrpm-e--nodepsmariadb-libs-5.5.60-1.el7_5.x86_64卸载mariadwgethttp://dev.mysql.com/get/mysql57-community-release-el7-11.
我是Ruby的新手。我安装了DataMapper并且正在尝试安装dm-mysql-adapter-1.0.2gem。但是当我尝试安装时,出现以下错误。我正在使用ubuntu操作系统。vinoth@vinoth-laptop:~/Downloads$geminstalldm-mysql-adapter-1.0.2----with-mysql-lib=/usr/lib/mysql----with-mysql-conf=/usr/bin/mysqlWARNING:Installingto~/.gemsince/home/vinoth/gemsand/home/vinoth/gems/bina
我正在学习rubyonrails的基础知识,我想做一些简单的查询,但我有疑问:我将拥有这些模型:classClient现在,我将使用脚手架来生成所有的东西,我想知道我是否必须直接将外键放在脚手架中,例如:rails生成脚手架地址street:stringnumber:integerclient_id:integer或者当我建立这些关联然后迁移我的数据库时,它们将是隐式的?我不知道我是否以最好的方式解释了自己。谢谢 最佳答案 是的,没有引用。您需要传递client_id或对Client模型的引用,例如:railsgenerates
我目前正在构建一个需要mysql2gem的RoR项目。我成功安装了gem。因为它出现在我的gem列表中。[root@vc2cmmka035538nsimple_cms]#gemlist***LOCALGEMS***actionmailer(3.2.3)actionpack(3.2.3)activemodel(3.2.3)activerecord(3.2.3)activeresource(3.2.3)activesupport(3.2.14,3.2.3)arel(3.0.2)bigdecimal(1.1.0)builder(3.2.2,3.0.0)bundler(1.1.5)c2c_li