**主键约束(Primary Key)
用于标记表格中数据的唯一存在(要求 1,主键不能为null,2,唯一的值不能重复)
添加主键的语句(改的是表的结构DDL)
alter table 表名 add constraint 约束名字 约束类型(列);
alter table student add constraint pk_student primary key(sid);
给学生表格 sid列 添加一个 pk_student 名字的 primary key类型的主键;
desc student;//description 显示表格的详细类型;
show keys from 表名;//显示表格的主键;
简写添加主键的语句
alter table 表名 add primary key( sid );
可以手动让数据库自动自增主键:
1,alter table student modify sid int(4) aoto_increment; (默认从 1 开始)
2,alter table student change sid sid int (4) aoto_increment;
change 和 modify
区别 modify改的是主键的自增
change改变的是主键的列和逐渐的列的类型
去除主键约束
alter table student drop primary key;
主键去除以后 原来的主键的非空的属性还在,需要更改不要非空
把表格中的非空状态更改为可以为空;
alter table student modify sid int(4) null;
*唯一约束(Unique [Key] )
表格中的某一个列添加唯一约束 和主键类似 不可重复,可以为空
添加唯一约束
alter table 表名 add constraint 主键名 unique [key] (列);
alter table 表名 add constraint uk_myclass unique [key] (sid);
简写:
alter table 表名 add unique [key] (sid);(某认约束名)
删除唯一约束:
alter table drop index 约束名字;
非空约束(Multiple)
在列上约束不能为空
alter table 表名 modify 原列名 原类型 原长度 not null ;
alter table 表名 change 原列名 原列名 原类型 原长度 not null ;(change可以更改表名)
可以设置不为空的列的默认值:
alter table 表名 modify 原列名 原类型 原长度 not null default ' AAAAAA ';
把 表的列名设置不能为空 并且默认值为AAA
**外键约束(Foreign Key)
约束自己表格的信息不能随意填写
外键是当前的表格 受到另一个表格某一个列的影响。
如 员工表和部门表
id 部门1 名字--------部门2 地点
员工表的部门 只能 是在部门表 里面的 部门内 信息找寻;
添加员工信息的时候,要在部门表之中信息寻找,且部门内的信息不能重复!
1,添加外键约束
alter table 表名 add constraint fk_当前表_关联表 foreign key (列名字) references 另一个表(列);
alter table 员工表add constraint fk_ 员工表名_部门表名 foreign key (部门1) references 部门表名(部门2);
2,查询表格主键
show keys from 表;/ desc 表;(PRI 主键 UNI 唯一 MUL外链 )
3,删除外键约束
alter table 表名字 drop foreign key 约束名字(就是fk_A_B);
通过上述语句 外键约束删掉了 。会自动在当前表格内添加一个新的key(这个key是第二个和第一个
表格的关联),所以要再次删除:alter table 表名 drop key 约束名字;
show creat table 表名字;显示创建表格的语句;
------------------------------------------简写---------------------------------------------
alter table student add foreign key(A列名)references B表名(B列名);
检查约束
给一个列的一个细致的范围,检查范围是否合理:
添加检查约束:
alter table 表名 add constraint ck_sage check(sage>15 and sage<35);
删除检查约束:
======================表格之间的关系==============================
一对多
班级--------学生
一端主键约束 多端外键约束
A B
classid loc sid sname classid
一般两个表格的外键约束 名字最好要一致 有助于可读性如上的 classid 一看就是外键约束
其中的A表的classid是一端 所以需要主键约束(Primary Key);
B表中的classid是多端 需要外键约束(foregin key);
再加上B中的原有的需要主键约束的sid
多对多
老师-----------学生
用的还是外键约束,但是如果吧所有的约束都放在一个表格中,会造成表格存储麻烦等
所以吧多对多的外键约束的信息新建一个 新的中间表格
说白了就是A对B是多对多,
A对中间表是一对多;
B对中间表是一对多;
一对一
人------------身份证
1,一对多然后把多端设置成为唯一的。
2,可以吧B的主键作为A的外键。
就可以从A到B是一对一,在从B到A是一对一的关系
一对一最好可以设置成一张表格;
=====================*****联合查询=====================
小补充(广义笛卡尔积)
A行数*B行数(本质就是A1和B1--A1B2----A1B3一直A行数和B行数排列完整)
select * from A,B;
对于上面的笛卡尔积算出来的数据不一定有用就需要筛选
列 行 A1 A2 A3 B1 B2
A1 B1
A1 B2
A2 B1
A2 B2
A3 B1
A3 B2
等值链接
对于笛卡尔积进行筛选就叫等值链接
对于有重复的列名 需要用 表名.列名 进行确定
任何表格都可以用等值链接查询
由于以上等值链接性能低所以引出了一下两个方法:
select* from A , B where 条件 { A.name =/>/</<=/>= B.name} ;
外连接
select * from A left/right [outer] join B on 条件
本身语句的注意点:
1,A和B表格 A先出现所以A在左边出现。 B在右边出现;
2,left和right 控制以哪一个表格作为基准
作为基准,会把基准的表格全部显示,
基准的表格显示之后,和另一个表格比较,比较不出来的就显示空;
和等值链接区别
1,在链接的时候就找on后面的条件,所以条件是必须的(连一次找一次条件)
2,等值链接是先链接,后按条件筛选(性能慢);
内连接
select * from A inner join B on 条件;
和等值链接区别 只显示符合条件的
1,查询结果和等值链接结果一致;
2,内连接不分左右 不能省略inner关键字;
3,可以查询两张完全不一样的表格;
4,A和B表格可以是相同的一个;
必须给表格起一个别名
可能还需要给当前的表格有一定的设计
===================SQL综合练习==========================
mysql> select * from country;
+-----+--------+
| cid | cname |
+-----+--------+
| 1 | 中国 |
| 2 | 美国 |
| 3 | 日本 |
+-----+--------+
cid主键
============================
mysql> select * from area
-> ;
+-----+-----------+------+
| aid | aname | cid |
+-----+-----------+------+
| 1 | 北方 | 1 |
| 2 | 南方 | 1 |
| 3 | 西部 | 2 |
| 4 | 东部 | 2 |
| 5 | 北海道 | 3 |
| 6 | 四国 | 3 |
+-----+-----------+------+
aid主键 cid和country的cid外键
====================================
mysql> select* from city;
+--------+-----------+----------+------+
| cityid | cityname | citysize | aid |
+--------+-----------+----------+------+
| 1 | 哈尔滨 | 750 | 1 |
| 2 | 大连 | 50 | 1 |
| 3 | 北京 | 2000 | 1 |
| 4 | 上海 | 1500 | 2 |
| 5 | 杭州 | 800 | 2 |
| 6 | 洛杉矶 | 1200 | 3 |
| 7 | 休斯顿 | 750 | 3 |
| 8 | 纽约 | 1000 | 4 |
| 9 | 底特律 | 500 | 4 |
| 10 | 东京 | 1500 | 5 |
| 11 | 名古屋 | 50 | 5 |
| 12 | 大板 | 20 | 6 |
+--------+-----------+----------+------+
city是主键 aid和area表的aid外键
===========================
1.查询人口数在1000到2000之间的城市 所属在哪个地区
select aname from city ci inner join area a on a.aid=ci.aid where citysize between 1000 and 2000;
2.查询每个国家的城市个数 按照城市个数升序排列
select cname,count(c.cid) as coun from city ci inner join area a on a.aid=ci.aid inner join country c on c.cid=a.cid group by cname order by coun;
3.查询各地区城市人口平均数 按照人口平均数降序排列
select a.aname,avg(ci.citysize) as ag from city ci inner join area a on a.aid=ci.aid group by a.aname order by ag desc;
4.查询哈尔滨所在的国家 的名字
select c.cname from city ci inner join area a on a.aid=ci.cid inner join country c c.cid=a.cid where ci.cityname='哈尔滨' ;
5.查询各地区名字 和人口 总数
select a.aname,sum(ci.citysize) as sm from city ci inner join area a on a.aid=ci.aid group by a.aname;
6.查询美国有哪些城市 列出城市名
select ci.cityname from city ci inner join area a on a.aid=ci.aid inner join country c on c.cid=a.cid group by cname ;
7.查询人口最多的城市在哪个国家
select cname sum(city.cityname) as sm from city inner join area on city.aid=area.aid inner join country c on c.cid=area.aid group by cname where sm =(select ) ;
8.查询每个国家的人口总数
select c.cname ,sum(ci.citysize) as sm from city ci inner join area a on a.aid=ci.aid inner join country c on c.cid=a.cid group by c.cname ;
9.查询城市人口数为1500万 的国家名字
select c.cname from city ci inner join area a on ci.aid=a.aid inner join country c on c.cid=a.cid where ci.citysize=1500 ;
10.查询各地区总人数 按照人口数总量降序排列
select a.aname ,sum(ci.citysize) as sm from city ci inner join area a on a.aid=ci.aid group by a.aname order by sm desc;
11.查询人口总数超过5000的国家 名称
select cname from city ci inner join area a on a.aid=ci.aid inner join country c on c.cid= a.cid group by cname having sum(ci.citysize) as sm sm>5000;(先分组在筛选用having)
12.查询人口数大于杭州的城市都有哪些
select cityname from city where citysize>(select citysize from city where cityname='杭州');