一镜盯、sql概述
sql:Structure Query Language,結(jié)構(gòu)化查詢語言
二、sql分類
1枉层、DDL
DDL,即Data Definition Language赐写,數(shù)據(jù)定義語言鸟蜡,用來定義數(shù)據(jù)庫對象:庫、表和列等挺邀。
使用的關(guān)鍵字:CREATE,ALTER,DROP
1.1揉忘、操作數(shù)據(jù)庫:
create database mydb character set utf8 collate gbk_chinese_ci
collate:指定數(shù)據(jù)庫字符集的比較方式
show databases
show create database mydb
alter database mydb character set gbk
drop database mydb
use mydb
select database()
1.2跳座、操作數(shù)據(jù)表:
MySQL常用數(shù)據(jù)類型:
int:整型
double:浮點型,例如double(5,2)表示最多5位泣矛,其中必須有2位小數(shù)疲眷,即最大值為999.99
char:固定長度字符串類型; char(10) 'abc'
varchar:可變長度字符串類型您朽;varchar(10) 'abc'
text:字符串類型
blob:字節(jié)類型
date:日期類型咪橙,格式為:yyyy-MM-dd
time:時間類型,格式為:hh:mm:ss
timestamp:時間戳類型 yyyy-MM-dd hh:mm:ss 會自動賦值
datetime:日期時間類型 yyyy-MM-dd hh:mm:ss
CREATE TABLE emp(
id INT,
NAME VARCHAR(20),
gender VARCHAR(10),
birhtday DATE,
Entry_data DATE,
job VARCHAR(20),
Salary DOUBLE,
RESUME TEXT
)
show tables
desc emp
alter table emp add image blob
alter table emp modify job varchar(60)
alter table emp drop image
rename table emp to user
show create table user
alter table user character set gbk
alter table user change name username varchar(20)
2虚倒、DML
DML美侦,即Data Manipulation Language,數(shù)據(jù)操作語言魂奥,用來操作數(shù)據(jù)庫表中的數(shù)據(jù)菠剩。
使用的關(guān)鍵字:INSERT,UPDATE,DELETE
INSERT INTO USER(id,username,gender,birthday,Entry_data,job,Salary,RESUME)
VALUES(1,'周杰倫','m','1978-5-12','2016-11-22','actor','100000.00','Music King')
INSERT INTO USER VALUES
(2,'周杰倫2','m','1978-5-12','2016-11-22','actor','100000.00','Music King'),
(3,'周杰倫3','m','1978-5-12','2016-11-22','actor','100000.00','Music King')
update user set job='actor&singer'
update user set job='singer' where id=2
update user set Salary=Salary * 9 where id=3
delete from user where username='周杰倫'
delete from user
truncate table user
DELETE:
刪除表中的數(shù)據(jù),表結(jié)構(gòu)還在
刪除后的數(shù)據(jù)可以找回
TRUNCATE:
把表直接DROP掉耻煤,然后再創(chuàng)建一個同樣的新表
刪除的數(shù)據(jù)不能找回
執(zhí)行速度比DELETE快
Attention:以上的sql語句句末都沒有分號具壮,單句執(zhí)行沒有問題,但是想要多句一起執(zhí)行就血崩了哈蝇,所以棺妓,以后還是都加上分號。
3炮赦、DQL
DQL怜跑,即Data Query Language,數(shù)據(jù)操作語言吠勘,用來查詢記錄(數(shù)據(jù))性芬。查詢返回的結(jié)果集是一張?zhí)摂M表,對數(shù)據(jù)庫本身沒有影響剧防。
關(guān)鍵字:SELECT
語法:
SELECT 列名 FROM表名【W(wǎng)HERE --> GROUP BY -->HAVING--> ORDER BY】
SELECT selection_list /要查詢的列名稱/
FROM table_list /要查詢的表名稱/
WHERE condition /行條件/
GROUP BY grouping_columns /對結(jié)果分組/
HAVING condition /分組后的行條件/
ORDER BY sorting_columns /對結(jié)果分組/
LIMIT offset_start, row_count /結(jié)果限定/
首選建一個供之后查詢用的表:
CREATE TABLE stu (
sid CHAR(6),
sname VARCHAR(50),
age INT,
gender VARCHAR(50)
);
INSERT INTO stu VALUES('S_1001', 'liuYi', 35, 'male');
INSERT INTO stu VALUES('S_1002', 'chenEr', 15, 'female');
INSERT INTO stu VALUES('S_1003', 'zhangSan', 95, 'male');
INSERT INTO stu VALUES('S_1004', 'liSi', 65, 'female');
INSERT INTO stu VALUES('S_1005', 'wangWu', 55, 'male');
INSERT INTO stu VALUES('S_1006', 'zhaoLiu', 75, 'female');
INSERT INTO stu VALUES('S_1007', 'sunQi', 25, 'male');
INSERT INTO stu VALUES('S_1008', 'zhouBa', 45, 'female');
INSERT INTO stu VALUES('S_1009', 'wuJiu', 85, 'male');
INSERT INTO stu VALUES('S_1010', 'zhengShi', 5, 'female');
INSERT INTO stu VALUES('S_1011', 'xxx', NULL, NULL);
3.1植锉、基礎查詢
SELECT * FROM stu;
select sname,gender from stu;
3.2、條件查詢
使用關(guān)鍵字where峭拘,運算符和關(guān)鍵字如下:
- =俊庇、!=、<>鸡挠、<辉饱、<=、>宵凌、>=鞋囊;
- BETWEEN…AND;
- IN(set)瞎惫;
- IS NULL溜腐; IS NOT NULL
- AND;
- OR瓜喇;
- NOT挺益;
其中between ... and... 等價于>= <=
select * from stu where gender='female' and age>=50;
select * from stu where age between 25 and 45;
select * from stu where sid in ('s_1001','s_1003','s_1005');
select * from stu where age is null;
3.3、模糊查詢
使用關(guān)鍵字like乘寒,通配符:
- _表示任意一個字符
- %表示任意多個字符
select * from stu where sname like '%c%';
select * from stu where sname like '_h';
3.4望众、字段控制查詢
去重查詢
使用關(guān)鍵字distinct。
select distinct gender from stu;
數(shù)值類型做四則運算
增加一列數(shù)值以便測試:
ALTER TABLE stu ADD height DOUBLE;
UPDATE stu SET height=174;
UPDATE stu SET height=NULL WHERE age<20;
注意任何值與NULL相加結(jié)果還是NULL伞辛,所以要使用ifnull函數(shù)烂翰。
SELECT *,age+height FROM stu;
SELECT *,IFNULL(age,0)+IFNULL(height,0) FROM stu;
給列名添加別名
使用關(guān)鍵字as,可省略蚤氏。
SELECT *,IFNULL(age,0)+IFNULL(height,0) AS total FROM stu;
SELECT *,IFNULL(age,0)+IFNULL(height,0) 合計 FROM stu;
3.5甘耿、排序
使用關(guān)鍵字order by。
- asc竿滨,默認值佳恬,升序
- desc,降序
UPDATE stu SET age='5' WHERE age IS NULL;
UPDATE stu SET height=178 WHERE height IS NULL;
/*以上對數(shù)據(jù)進行改造以便測試*/
SELECT * FROM stu ORDER BY age;
SELECT * FROM stu ORDER BY age,height DESC;
3.6于游、聚合函數(shù)
聚合函數(shù)是用來做縱向運算的函數(shù):
- COUNT():統(tǒng)計指定列不為NULL的記錄行數(shù)
- MAX():計算指定列的最大值毁葱,如果指定列是字符串類型,那么使用字符串排序運算
- MIN():計算指定列的最小值贰剥,如果指定列是字符串類型倾剿,那么使用字符串排序運算;
- SUM():計算指定列的數(shù)值和蚌成,如果指定列類型不是數(shù)值類型柱告,那么計算結(jié)果為0;
- AVG():計算指定列的平均值笑陈,如果指定列類型不是數(shù)值類型际度,那么計算結(jié)果為0;
select count(*) from stu;
/*查詢有年齡的涵妥,即age不為null*/
select count(age) from stu;
select count(*) from stu where age>50;
select count(*) from stu where ifnull(age,0)+ifnull(height,0)>250;
select sum(height),sum(age),sum(gender),avg(age) from stu;
select max(age),min(height) from stu;
3.7乖菱、分組查詢
使用關(guān)鍵字group by
select gender,avg(age) from stu group by gender;
select gender,avg(age) from stu where gender is not null group by gender;
select gender,avg(age) from stu where gender is not null group by gender having avg(age)>50;
having與where的區(qū)別:
- having是在分組后對數(shù)據(jù)進行過濾,where是在分組前對數(shù)據(jù)進行過濾
- having后面可以使用聚合函數(shù)(統(tǒng)計函數(shù))蓬网,where后面不可以使用聚合函數(shù)
- where是對分組前記錄的條件窒所,如果某行記錄沒有滿足where子句的條件,那么這行記錄不會參加分組帆锋;而having是對分組后數(shù)據(jù)的約束
3.8吵取、limit
/*查詢m行記錄,起始行從n開始*/
select * from stu limit n,m;
- 查詢語句書寫順序:select – from- where- group by- having- order by-limit
- 查詢語句執(zhí)行順序:from - where -group by - having - select - order by-limit
三锯厢、數(shù)據(jù)完整性
1皮官、實體完整性
實體:表中的一行脯倒,或者說一條記錄。
作用:標識每一行數(shù)據(jù)不重復捺氢。
約束類型:
- 主鍵約束(primary key)
- 唯一約束(unique)
- 自動增長列(auto_increment)
1.1藻丢、主鍵約束
每個表中都要有一個主鍵,數(shù)據(jù)唯一摄乒,不能為null悠反。
添加方式如下:
create table student(
id int primary key,
name varchar(50)
);
/*此方式可以創(chuàng)立聯(lián)合主鍵*/
create table student(
id int,
name varchar(50),
primary key(id)
);
create table student(
stuid int,
classid int,
name varchar(50),
primary key(stuid,classid)
);
create table student(
id int,
name varchar(50)
);
alter table student add primary key(id);
alter table student add constraint pk_stu_id primary key(id);
/*刪除主鍵約束*/
alter table student drop primary key;
1.2、唯一約束
特點:數(shù)據(jù)不能重復馍佑。
create table student(
id int primary key,
name varchar(50),
tag varchar(50) unique
);
1.3斋否、自動增長列
并不是只能用于主鍵,但該列只能是整數(shù)類型
其他數(shù)據(jù)庫關(guān)鍵字:
- sqlserver:identity
- oracle:sequence
create table student (
id int primary key auto_increment,
name varchar(50)
)
insert into student(name) values('Jay');
2拭荤、域完整性
作用:限制此單元格的數(shù)據(jù)正確茵臭,域代表當前單元格。
域完整性約束:
- 數(shù)據(jù)類型約束
- 非空約束(not null)
- 默認值約束(default)
- check約束穷劈,check(sex='男' or sex='女')笼恰,MySQL不支持
create table student(
id int primary key,
name varchar(50) not null,
sex varchar(10) default '女'
);
insert into student values(1,'張小凡','男');
insert into student values(2,'碧瑤',default);
insert into student(id,name) values(3,'陸師姐');
3、引用完整性
外鍵約束:foreign key
create table student(
id int primary key,
name varchar(50) not null,
sex varchar(10) default '女'
);
create table score(
scoreid int,
score double,
stuid int,
constraint fk_student_score_stuid foreign key(stuid) references student(id)
);
/*另一種方式*/
alter table score add constraint fk_student_score_stuid foreign key(stuid) references student(id);
/*刪除外鍵約束*/
alter table score drop foreign key fk_student_score_stuid;
4歇终、表與表之間的關(guān)系
- 一對一社证,比如人和身份證
- 一對多(多對一),比如學生和考試
- 多對多评凝,比如老師和學生
四追葡、多表查詢
種類:
- 合并結(jié)果集:union、union all
- 連接查詢
- 內(nèi)連接:[inner] join on
- 外連接:outer join on
- 左外連接:left [outer] join
- 右外連接:right [outer] join
- 全連接:full join(MySQL不支持)
- 外連接:outer join on
- 子查詢
1奕短、合并結(jié)果集
作用:把兩個select語句的查詢結(jié)果合并到一起宜肉。
方式:
- union:去除重復記錄
- union all:不去除重復記錄
要求:被合并的兩個結(jié)果,列數(shù)翎碑、列類型必須相同谬返。
select * from t1 union select * from t2;
select * from t1 union all select * from t2;
2、連接查詢
連接查詢就是求出多個表的乘積日杈,例如t1連接t2遣铝,那么查詢出的結(jié)果就是t1*t2。
顯然莉擒,一般情況下這都不是我們想要的結(jié)果酿炸,所以,要使用主外鍵關(guān)系來去除無用信息涨冀。
drop table score;
CREATE TABLE score(
scoreid INT,
scorename varchar(50),
score DOUBLE,
stuid INT,
CONSTRAINT fk_student_score_stuid FOREIGN KEY(stuid) REFERENCES student(id)
)
insert into score values(1,'java',99,1),
(2,'java',90,2),
(3,'java',92,3),
(4,'mysql',95,1);
SELECT * FROM student,score;
SELECT * FROM student stu,score sco WHERE stu.id=sco.stuid;
2.1填硕、內(nèi)連接
上述的語句就是內(nèi)連接,但不是sql中標準的查詢方式鹿鳖,標準的內(nèi)連接如下:
select * from student stu join score sco on stu.id=sco.stuid;
再向student表中插入一條數(shù)據(jù):
insert into student values(4,'花千骨',default);
但是score表里沒有花千骨的記錄扁眯,也就是說她缺考了壮莹,此時使用內(nèi)連接就只能查出參加了考試的學生。想要查出所有學生恋拍,那么就得使用外連接垛孔。
2.2藕甩、外連接
特點:查詢出的結(jié)果存在不滿足條件的情況施敢。
- 左連接:先查詢出左表(即以左表為主),然后查詢右表狭莱,右表中滿足條件的顯示出來僵娃,不滿足條件的顯示NULL
- 右連接:先把右表中所有記錄都查詢出來,然后左表滿足條件的顯示腋妙,不滿足顯示NULL
select * from student stu left join score sco on stu.id=sco.stuid;
select * from student stu right join score sco on stu.id=sco.stuid;
2.3默怨、自然連接
上述的連接查詢都會出現(xiàn)多余的結(jié)果,更加準備的說法稱之為無用的笛卡爾積骤素,需要通過主外鍵關(guān)系來去除匙睹。而自然連接則不需要這個關(guān)系,它會自動找到這一關(guān)系济竹。
條件:兩張連接的表中存在名稱和類型完全一致的列痕檬。
/*以下是不能查詢成功的*/
select * from student natural join score;
select * from student natural left join score;
select * from student natural right join score;
/*執(zhí)行以下語句,將列名統(tǒng)一為stuid之后再
執(zhí)行上述語句就可以查詢到先要的結(jié)果了*/
ALTER TABLE score DROP FOREIGN KEY fk_student_score_stuid;
ALTER TABLE student CHANGE id stuid INT;
ALTER TABLE score ADD CONSTRAINT fk_student_score_stuid FOREIGN KEY(stuid) REFERENCES student(stuid);
2.4送浊、子查詢
子查詢就是嵌套查詢梦谜,即SELECT中包含SELECT,如果一條語句中存在兩個袭景,或兩個以上SELECT唁桩,那么就是子查詢語句了。
創(chuàng)建職員表和部門表:
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno INT
) ;
INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
CREATE TABLE dept(
deptno INT,
dname VARCHAR(14),
loc VARCHAR(13)
);
INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept VALUES(20, 'RESEARCH', 'DALLAS');
INSERT INTO dept VALUES(30, 'SALES', 'CHICAGO');
INSERT INTO dept VALUES(40, 'OPERATIONS', 'BOSTON');
開始子查詢:
/*查詢工資高于JONES的員工*/
select * from emp where sal > (select sal from emp where ename='JONES');
/*查詢工資高于30號部門所有人的員工信息*/
SELECT * FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno=30);
SELECT * FROM emp WHERE sal > ALL (SELECT 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);
/*查詢員工編號為7788的員工名稱荒澡、員工工資、部門名稱与殃、部門地址*/
select e.ename,e.sal,d.dname,d.loc from emp e,dept d where e.deptno=d.deptno and e.empno=7788;
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, (SELECT dname,loc,deptno FROM dept) d
WHERE e.deptno=d.deptno AND e.empno=7788
2.5单山、自連接
自己連接自己,起別名奈籽。
/*查詢7369員工編號饥侵、姓名、經(jīng)理編號和經(jīng)理姓名*/
select e1.empno,e1.ename,e2.mgr,e2.ename from emp e1,emp e2 where e1.empno=7369 and e1.mgr=e2.empno;
Have a try:
查詢各個部門薪水最高的員工所有信息
INSERT INTO emp VALUES(7782,'test','MANAGER',7839,'1981-06-09',3000,NULL,10);
/*錯誤的查詢方式*/
select * from emp where sal in (select max(sal)from emp group by deptno);
/*正解*/
select e.* from emp e,(select max(sal) max,deptno from emp group by deptno)m where e.deptno=m.deptno and e.sal=m.max;