作用:保证用户输入的数据保存到数据库中是正确的。
确保数据的完整性 = 在创建表时给表中添加约束
完整性的分类:
实体: 即表中的一行(一条记录)代表一个实体(entity)
实体完整性的作用:标识每一行数据不重复
约束类型: 主键约束(primary key) 唯一约束(unique) 自动增长列(auto_increment)
注:每个表中要有一个主键。
特点:数据唯一,且不能为null
例子:
第一种添加方式:
CREATE TABLE student(
id int primary key,
name varchar(50)
);
第二种添加方式:
CREATE TABLE student(
id int,
name varchar(50),
primary key(id)
);
CREATE TABLE student(
classid int,
stuid int,
name varchar(50),
primary key(classid,stuid)
);
此种方式优势在于,可以创建联合主键
第三种方式:
CREATE TABLE student(
id int,
name varchar(50)
);
ALTER TABLE student ADD PRIMARY KEY (id);
特点: 数据不能重复
CREATE TABLE student(
Id int primary key,
Name varchar(50) unique
);
自动增长列(auto_increment)
这种用法只限于mysql,其他数据库略有不同
CREATE TABLE student(
Id int primary key auto_increment,
Name varchar(50)
);
INSERT INTO student(name) values(‘tom’);
域完整性的作用:限制此单元格的数据正确,不对照此列的其它单元格比较
域代表当前单元格
域完整性约束:数据类型 非空约束(not null) 默认值约束(default)
check约束(mysql不支持)check(sex=’男’ or sex=’女’)
CREATE TABLE student(
Id int pirmary key,
Name varchar(50) not null,
Sex varchar(10)
);
INSERT INTO student values(1,’tom’,null);
CREATE TABLE student(
Id int pirmary key,
Name varchar(50) not null,
Sex varchar(10) default ‘男’
);
insert into student1 values(1,'tom','女');
insert into student1 values(2,'jerry',default);
外键约束(实际开发中基本上不会使用)
例:
CREATE TABLE student(
sid int pirmary key,
name varchar(50) not null,
sex varchar(10) default ‘男’
);
create table score(
id int,
score int,
sid int , -- 外键列的数据类型一定要与主键的类型一致
CONSTRAINT fk_score_sid foreign key (sid) references student(id)
);
第二种添加方式
ALTER TABLE score ADD CONSTRAINT fk_stu_score FOREIGN KEY(sid) REFERENCES stu(id);
外键会保证score中的数据是student表中sid这一列已经存在的值
多表查询有如下几种:
SELECT * FROM t1 UNION SELECT * FROM t2;
SELECT * FROM t1 UNION ALL SELECT * FROM t2。
既然是多表查询,那么我们先来看看两张非常简单的表,我们就以这两张表为例,进行演示。
student表
班级表
同时查询这两张表
select * from student,class;
仔细观察查询出的数据,可以发现,当使用上图中的语句时,student表中的每一行记录,都与class表中的任意一条记录相关联,同样,class表中的每一行记录,都与student表中的任意一条记录相关联。即当我们有2张表时,交叉连接的效果如下:
我们把上述”没有任何限制条件的连接方式”称之为”交叉连接”,”交叉连接”后得到的结果跟线性代数中的”笛卡尔乘积”一样。
笛卡尔积: 假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况
“交叉连接”的英文原文为”cross join”,被咱们翻译为交叉连接,其实,上述示例中的语句我们可以换一种写法,两种写法能够获取到相同的结果,示例如下
SELECT * FROM student CROSS JOIN class;
只不过在mysql中 我们可以简化为上述的写法
多表查询产生这样的结果并不是我们想要的,那么怎么去除重复的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系去除笛卡尔积
既然”交叉连接”不常用,那么肯定有其他的常用的”多表查询方式”。我们来看看另一种常用的多表查询的方式:内连接
扔用刚才的两张表student和class为例,首先回顾一下两张表的内容:
那么什么是”内连接”呢?我们可以把”内连接”理解成”两张表中同时符合某种条件的数据记录的组合”,例如在查出的数据中同时展现学生信息和他们所在的编号,示例如下:
SELECT * FROM student, class where student.
上述的sql语句就使用了”内连接”,对比交叉连接发现,其实内连接就是交叉连接有更多的限制条件,内连接的英文原文为inner join,所以sql还可以写成
SELECT * FROM student INNER JOIN class ON student.sid = class.cid;
上述的是等值内连接,还可以有不等值内连接
SELECT * FROM student INNER JOIN class ON student.sid > class.cid;
这样内连接可以用图来表示:
使用”内连接”语句查询出的结果集是两个集合中”同时满足条件的数据”的”组合”,所以我们并不能单纯的用”交集”去表示这个组合,就以上图为例,按照”交集”的定义,属于集合A且同时属于集合B的元素所组成的集合被称为交集,但是上图中,id号为1的元素只属于t1表,在t2表中并不存在id号为1的元素,但是,上图中”中间”的结果集就是”内连接”查询出的结果,所以,我们不能单纯的用”交集”表示”内连接”,但是,我们可以从另一个角度定义”交集”,我们定义,”交集”为”两个集合中同时满足条件的数据的组合”
“内连接”除了”等值连接”与”不等连接”,还有一种分类,被称作”自连接”,自连接可以理解为比较特殊的”内连接”,刚才说到的”等值连接”与”不等连接”所连接的表为两张不同的表,而”自连接”连接的表为一张表,也就是自己连接自己,所以被称为”自连接”
我们再创建一张员工表,:
如图 员工表有上级属性,上级指向的是员工的ID,如果我们想把每个人的上级都显示出来可以使用语句:
SELECT * FROM emp AS e1 INNER JOIN emp AS e2 ON e1.superior = e2.id;
这就属于自连接,在自连接的时候,由于表名是相同的,需要给表名起一个别名
外连接分为两种,左外连接,和右外连接,外连接的特点,结果集中有不满足情况的
首先还是学生和班级表,不过我们学生表中插入了一个新学生,他还没有确定班级
使用左外连接,查询学生信息和它对应的班级
SELECT * FROM temp.student LEFT JOIN temp.class ON sid = cid;
左外连接不仅会查询出两表中同时符合条件的记录的组合,同时还会将”left join”左侧的表中的不符合条件的记录同时展示出来,由于左侧表中的这一部分记录并不符合连接条件,所以这一部分记录使用”空记录”进行连接。即左表的数据会完全的加载出来,即使右表中没有符合条件的数据
右连接与之类似
SELECT * FROM temp.class RIGHT JOIN temp.student ON sid = cid;
一个select语句中包含另一个完整的select语句。
子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。
原始数据表
工资高于JONES的员工
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES')
-- 一行一列
查询与SCOTT同一个部门的员工
SELECT *
FROM lan_ou.emp
WHERE deptno = (SELECT deptno
FROM lan_ou.emp
WHERE ename = 'SCOTT');
工资高于30号部门所有人的员工信息
SELECT * FROM emp WHERE sal>(
SELECT MAX(sal) FROM emp WHERE deptno=30);
查询工作和工资与MARTIN完全相同的员工信息
SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='MARTIN')
查询有2个以上直接下属的员工信息
SELECT *
FROM emp
WHERE empno IN (
SELECT mgr
FROM emp
GROUP BY mgr
HAVING COUNT(mgr) >= 2);
mysqldump –hlocalhost –uroot –p databaseName >d:\dump.sql (window)