一、首先,我们可以查看数据库的各种变量:
1.SHOW VARIABLES 查看数据库的变量
2.查看当前数据库的编码
SHOW VARIABLES WHERE variable_name LIKE 'character%';
3.解决中文乱码,如下三个编码保持一致就可以。
character_set_client、character_set_connection、character_set_results
二、子查询
4.case-when then end
SELECT sno,sname,age,saddress,(CASE sex WHEN '0' THEN '女' WHEN '1' THEN '男' ELSE '泰国' END)AS
性别 FROM sstud;
5.无关子查询
//查询具有相同年龄的人 --每年年龄段只显示一个代表
SELECT * FROM sstud GROUP BY age HAVING COUNT(age)>=2;
SELECT * FROM sstud WHERE age IN(
SELECT age FROM sstud GROUP BY age HAVING COUNT(age)>=2
);
//再加条件 age>20
SELECT * FROM sstud WHERE age IN(
SELECT age FROM sstud GROUP BY age HAVING COUNT(age)>=2 AND age>20
);
6.相关子查询
SELECT xs.name,xs.age, th.name, count(*) as c FROM sstud as xs, teacher as th WHERE age IN(
SELECT age FROM sstud where th.age>45 and c>2 GROUP BY age HAVING COUNT(age)>=2;
);
三、表与表之间的关系
数据库实体间有三种对应关系:一对一,一对多,多对多。
(一)、一对一
比如:夫妻就是一对一的关系(以下以夫妻表为例):
方式1:用两个独立的表来实现---项目用得更多的方式
CREATE TABLE wm(
id INT PRIMARY KEY,
NAME VARCHAR(10),
sex CHAR(1)
);
CREATE TABLE mm(
id INT PRIMARY KEY,
NAME VARCHAR(10),
sex CHAR(1),
wid INT UNIQUE, 注:外键,这一句表明wid属性与wm表中的id属性是一对一的,若没有这句则是一对多的。
CONSTRAINT mm_fk FOREIGN KEY(wid) REFERENCES wm(id) 注:设置外键
);
查询夫妻信息
SELECT mm.name AS 丈夫, wm.name AS 妻子 FROM mm, wm WHERE mm.wid=wm.id
方式2:用一个物理表来实现,同时创建两个虚拟表(视图)
需要两个表。当然做项目时为了省空间,通常只建一个表,如果要实现一对一的查询,可以建两个视图。示例如下:
1)建物理表,初始化数据
CREATE TABLE person(
id INT,
NAME VARCHAR(10),
sex CHAR(1),
wife INT,
husband INT
);
INSERT INTO person VALUES(1,'小花','0',0,3);
INSERT INTO person VALUES(2,'玉芬','0',0,4);
INSERT INTO person VALUES(3,'张三','1',1,0);
INSERT INTO person VALUES(4,'李四','1',2,0);
INSERT INTO person VALUES(5,'王五','1',0,0);
2) 建立两个视图
create view women as select * from person where sex='0';
create view men as select * from person where sex='1';
3) 查询夫妻信息
//旧版本
SELECT women.name AS 妻子, men.name AS 丈夫 FROM women, men WHERE women.husband = men.id;
---------------------------------
//采用内联接--98以后的新方式--效率更高
SELECT women.name AS 妻子, men.name AS 丈夫 FROM women INNER JOIN men ON women.husband = men.id;
这里就要讲到 关联了:
INNER JOIN(内联):两个表a,b 相连接,取出符合连接条件的字段
LEFT JOIN(左联):先返回左表的所有行,再加上符合连接条件的匹配行
RIGHT JOIN(右联):先返回右表的所有行,再加上符合连接条件的匹配行
1、内连接——最常用
定义:仅将两个表中满足连接条件的行组合起来作为结果集。
在内连接中,只有在两个表中匹配的行才能在结果集中出现
关键词:INNER JOIN
格式:SELECT 列名表 FROM 表名1 [INNER] JOIN 表名2 ON或WHERE 条件表达式
说明:
(1)列名表中的列名可以出自后面的两个表,但如果两个表中有同名列,应在列名前标明出处,格式为:表名.列名
(2)若连接的两个表名字太长,可以为它们起个别名。 格式为:表名 AS 别名
(3)INNER是默认方式,可以省略
2、左连接
定义:在内连接的基础上,还包含左表中所有不符合条件的数据行,并在其中的右表列填写NULL
关键字:LEFT JOIN
注意:
当在内连接查询中加入条件是,无论是将它加入到join子句,还是加入到where子句,其效果是完全一样的,但对于外连接情况
就不同了。
当把条件加入到 join子句时,SQL Server、Informix会返回外连接表的全部行,然后使用指定的条件返回第二个表的行。
3、右连接
定义:在内连接的基础上,还包含右表中所有不符合条件的数据行,并在其中的左表列填写NULL
关键字:RIGHT JOIN
4、完全连接 (mysql不支持)
定义:在内连接的基础上,还包含两个表中所有不符合条件的数据行,并在其中的左表、和右表列填写NULL
关键字:FULL JOIN
5.外连接(mysql不支持)
关键字:OUTTER JOIN
关联,可理解成把几个合成一个新的表,然后在新表中进行查询
(二)、一对多
数据库设计分析
※案例:一个人可以拥有多辆汽车,要求查询出某人所拥有的所有汽车。
方案一(差的设计):
编号 姓名 性别 年龄 汽车编号 车型 排量 价格
P001 Jack 男 25 C001 BMW 12L 80w
P001 Jack 男 25 C002 Benz 12L 100w
P001 Jack 男 25 C003 Benz 12L 100w
P002 Tom 男 25 C004 BMW 12L 80w
P002 Tom 男 25 C005 Benz 12L 100w
P003 Rose 女 25 C006 Benz 12L 100w
方案二(好的设计):
1)把一方单独建个表
编号 姓名 性别 年龄
P001 Jack 男 25
P002 Tom 男 25
P003 Rose 女 25
2)把多方也建个表(依赖一方,通过外键--补一个字段)
外键:位于依赖一方,它是被依赖一方是主键
汽车编号 车型 排量 价格 车主
C001 BMW 12L 80w P001
C002 Benz 12L 100w P001
C003 Benz 12L 120w P001
C004 BMW 12L 80w P002
C005 Benz 12L 100w P002
C006 Benz 12L 100w P003
3) 代码实现
CREATE TABLE person2(
id varchar(32) primary key,
NAME VARCHAR(30),
sex CHAR(1),
age INT
);
INSERT INTO person2 VALUES('P1001','小花','0',25);
INSERT INTO person2 VALUES('P1002','张三','1',22);
INSERT INTO person2 VALUES('P1003','Jack','1',24);
INSERT INTO person2 VALUES('P1004','Rose','0',25);
CREATE TABLE car(
id varchar(32) primary key,
NAME VARCHAR(30),
price numeric(10,2),
pid varchar(32),
/*为字段pid定义一个外键约束(来自person2表的字段id)*/
constraint car_fk foreign key(pid) references person2(id)
);
INSERT INTO car VALUES('C001','BMW',80.5,'P1001');
INSERT INTO car VALUES('C002','Benz',100,'P1001');
INSERT INTO car VALUES('C003','BMW',120.05,'P1001');
INSERT INTO car VALUES('C004','Benz',88.5,'P1002');
INSERT INTO car VALUES('C005','QQ',8.5,'P1002');
INSERT INTO car VALUES('C006','BIKE',0.5,'P1003');
1.哪些人有哪些车
SELECT * FROM person2 INNER JOIN car ON person2.id=car.pid;
SELECT person2.NAME,car.id,car.NAME,car.price FROM person2 INNER JOIN car ON person2.id=car.pid WHERE car.price>50;
2.Mike的车辆信息
SELECT person2.NAME,person2.age,car.id,car.NAME,car.price FROM person2 LEFT JOIN car ON person2.id=car.pid WHERE person2.NAME='Mike'
3.哪些人没有车
SELECT person2.NAME,person2.age,car.NAME FROM person2 LEFT JOIN car ON person2.id=car.pid WHERE car.NAME IS NULL;
4.哪些人至少有两辆车
//新版
SELECT person2.NAME,car.id FROM person2 INNER JOIN car ON person2.id=car.pid GROUP BY person2.NAME HAVING COUNT(*)>=2;
//旧版
SELECT NAME FROM person2 WHERE id IN('P1001','P1002');
SELECT NAME FROM person2 WHERE id IN( SELECT pid FROM car GROUP BY pid HAVING COUNT(*)>1 );
(三)、多对多
数据库设计分析
※案例:一个人可以选择多门课程,一门课程又可以被很多人选择。
方案一(差的设计):
1)学生表
编号 姓名 性别 年龄 电话 ...
P001 Jack 男 25
P002 Tom 男 25
P003 Rose 女 25
--------------------------
2)课程表
编号 名称 教材 学分... 学生
S001 Java ... ...... P001
S001 Java ... ...... P002
S001 Java ... ...... ...
S002 数据库 ... ...... P001
S002 数据库 ... ...... P002
......
方案二(好的设计:两个实体表+一个关系表):
1)学生表(独立)---实体
编号 姓名 性别 年龄 电话 ...
P001 Jack 男 25
P002 Tom 男 25
P003 Rose 女 25
2)课程表(独立)---实体
编号 名称 教材 学分...
S001 Java ... ......
S002 数据库 ... ......
S003 XML ... ......
3)选课表(专为体现多对多的关系而新增的表)--关系
课程编号 学生编号
S001 P001
S001 P002
...
S002 P002
S002 P003
...
S003 P001
...
外键 外键
| |
|━━━━|
|
联合主键
4) 代码实现
CREATE TABLE stud2(
id varchar(32) primary key,
NAME VARCHAR(30),
age INT
);
CREATE TABLE ject(
id varchar(32) primary key,
NAME VARCHAR(30)
);
CREATE TABLE sj(
studid varchar(32),
subjectid VARCHAR(32)
);
//单独添加约束(注意顺序: 要先添加联合主键,再添加外键)
//创建联合主键
ALTER TABLE sj ADD CONSTRAINT pk_sj PRIMARY KEY(studid,subjectid);
//创建两个外键
alter table sj add constraint fk_stud foreign key(studid) references stud(id);
alter table sj add constraint fk_subj foreign key(subjectid)references ject(id);
//删除外键---先添加外键再添加联合主键时,不行。删除外键,重来
ALTER TABLE sj DROP FOREIGN KEY fk_stud;
ALTER TABLE sj DROP FOREIGN KEY fk_subj;
1.查询哪些人选了哪些课
//92标准
select stud.name,ject.name from stud,ject,sj where stud.id=sj.studid and ject.id = sj.subjectid;
//96标准
select stud.name,ject.name from
stud inner join sj on stud.id=sj.studid
inner join ject on ject.id = sj.subjectid;
2查询哪些人没有选课
//92标准
SELECT stud.name FROM stud WHERE stud.id NOT IN (SELECT studid FROM sj );
//96标准--左关联
SELECT stud.name FROM stud LEFT JOIN sj ON stud.id=sj.studid LEFT JOIN ject ON ject.id = sj.subjectid
WHERE ject.NAME IS NULL;
//3查询哪些课程没人选
//96标准--左关联
SELECT ject.name FROM
ject LEFT JOIN sj ON ject.id=sj.subjectid
LEFT JOIN stud ON stud.id = sj.studid
WHERE stud.NAME IS NULL;
//96标准--右关联
SELECT ject.name,stud.name FROM
stud RIGHT JOIN sj ON stud.id=sj.studid
RIGHT JOIN ject ON ject.id = sj.subjectid
WHERE stud.NAME IS NULL;
※演示自动增长列与字段值唯一性约束
CREATE TABLE aa(
id INT AUTO_INCREMENT PRIMARY KEY,
nm VARCHAR(32) UNIQUE
);
INSERT INTO aa(nm) VALUES('uuu');