SQL入门基础语法,超详细

create database cgb2021 DEFAULT CHARACTER SET utf8;  #创建数据库

#创建  数据库   库名                       避免中文乱码(charset)

---------------------------------------------------

show databases; #查看数据库

#展示 所有数据库

---------------------------------------------------

drop database cgb2109; #删除库

#删除  数据库   库名

---------------------------------------------------

use cgb210901; #使用数据库

---------------------------------------------------

show tables;#查看所有的表

-------------------------------------------------------

create table tb_door(); #创建表

#创建    表     表名  (字段名称 字段类型(字段长度));

-------------------------------------------------------

drop table tb_door; #删除名称是 tb_door的表

-----------------------------------------------------

desc tb_door; #查看tb_door表结构

#描述  表名

------------------------------------------------------

alter table tb_room add column money NUMERIC(7,2);  #添加列

#修改  表    表名     增加  列   列名  字段类型(长度,精确到几位)

----------------------------------------------------------

select 列名1,列名2 from 表名--查询表名中列名1和列名2的数据

select 列名 别名,列名2 别名 from 表名

select  *  from  tb_order_detail; 查询tb_door表中的所有记录

查询  通配符/所有列  表名

SELECT * FROM emp; #查询所有列

SELECT ename FROM emp; #查名字列

SELECT empno,ename FROM emp;#查标号和名字

SELECT empno a FROM emp;#给列设置别名

--------------------------------------------------------------

insert into 表名 values(1,2,3,4);#向表中插入记录

#向表中插入数据    值们    给第一个字段赋值,

#注意:1.需要设置几个值?要看表里有几个字段

         #2.值的顺序要和字段的顺序保持一致

         #3.如果字段是字符串类型,设置值是必须要有“”‘’的标记。

----------------------------------------------------------------

update 表名 set tel=555 where id=1; #修改tb_door表中id为1的记录

#修改       设置 表里的字段名=修改后的新值

--------------------------------------------------------------------

delete from tb_order_detail;

#删除  表   表名

----------------------------------------------------------------

#主键约束 primary key

         #字段的值必须唯一,且不能为空,使用primary key

         当主键为数值类型时,为了方便维护,可以设置主键自增策略(auto_increment

设置了主键自增策略后,数据库会在表中保存一个AUTO_INCREMENT变量值,初始值为1,

当需要id值,不需要我们指定值,由数据库负责从AUTO_INCREMENT获取一个id值,

作为主键值插入到表中。而且每次用完AUTO_INCREMENT值,都会自增1.

————————————————-------------------------------------

非空约束 not null

如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复

--------------------------------------------------------------------

唯一约束 unique

         哪个字段添加了唯一约束,从此,字段值不能相同,使用unique

--------------------------------------------------------------------

lower--全转小写

SELECT ename,LOWER(ename) FROM emp;参数是列名

--------------------------------------------------------

upper--全转大写

SELECT ename,UPPER(ename) a FROM emp;参数是列名

-------------------------------------------------------

length--数据的长度,根据utf8,一个字母或数字长度为1,一个汉字长度为3

SELECT ename,LENGTH(ename) FROM emp;#查询ename的长度

-----------------------------------------------------------------------

substr--截取子串

substr(列名,a,b)a是截取谁,b是从哪个字符开始

SELECT ename,SUBSTR(ename,2) FROM emp;#从第二个截取到结束

SELECT ename,SUBSTR(ename,2,2) FROM emp;#第二个开始,截取2个数

------------------------------------------------------------------------

concat--拼接数据

concat(a,b,...)拼串--a是列名,b是要拼接的数据,...可以有多个参数

SELECT ename,CONCAT(ename,'hello',1,2) FROM emp;

-------------------------------------------------------------------------

replace--替换

replace(a,b,c)替换--a是字段名,把b换成c

SELECT ename,REPLACE(ename,'a','666')FROM emp;

-------------------------------------------------------------------------

ifnull(a,b)--a是字段名,b是要换成的值

SELECT comm,IFNULL(comm,100) FROM emp;#如果是null就换成100

--------------------------------------------------------------------------

round(a,b):四舍五入--a是列名,b是保留几位小数

SELECT comm,ROUND(comm) FROM emp;#四射五入取整

SELECT comm,ROUND(comm,1) FROM emp;#四舍五入保留一位小数

ceil:向上取整

SELECT comm,CEIL(comm) FROM emp;

floor:向下取整

SELECT comm,FLOOR(comm) FROM emp;

--------------------------------------------------------------------------

#对日期数据的函数

#now & year & month & day

SELECT NOW();#当前时间

SELECT YEAR('2019-3-12')

SELECT YEAR(NOW());#当前年

SELECT MONTH(NOW()),DAY(NOW());#当前月,当前日

#hour时 minute分 second秒

SELECT HOUR(NOW()),MINUTE(NOW()),SECOND(NOW());#当前时分秒

SELECT YEAR(NOW()),MONTH(NOW()),DAY(NOW()),HOUR(NOW()),MINUTE(NOW()),SECOND(NOW());

---------------------------------------------------------------------------

#生成一个32位随机数

SELECT UUID();

#\表示转义符号,把'当做普通的字符在使用,而不是字符串的标记

SELECT 'xi\'an';

----------------------------------------------------------------------------

#条件查询

#1.去重disrinct

SELECT loc FROM dept;

SELECT DISTINCT loc FROM dept;#查询部门地址

#2.where 连接查询的条件

#select 字段名 from表名 where 字段名=字段值

#练习1:查询编号为1的部门信息

SELECT * FROM dept WHERE deptno=1;

#练习2:查询编号>1的部门信息

SELECT * FROM dept WHERE deptno>2;

SELECT * FROM dept WHERE deptno<2;

SELECT * FROM dept WHERE deptno!=1;

SELECT * FROM dept WHERE deptno<>1;#表示不等于,同上

#练习三:查询名称是research的部门编号

SELECT deptno FROM dept WHERE dname='research';

----------------------------------------------------------------------------

#查询部门地址在二区的部门名称

SELECT dname FROM dept WHERE loc='二区';

#查询部门地址在二区名字里有o的部门编号

SELECT deptno FROM dept WHERE loc='二区' AND dname LIKE '%o%';

#查询名字以1开头的员工岗位并去重

SELECT DISTINCT job FROM emp WHERE ename LIKE 'l%';

#查询15年到19年入职的员工姓名和岗位

SELECT job,ename FROM emp WHERE

YEAR(hiredate)>=2015 AND YEAR(hiredate)<=2019;

#查询副总的年薪

SELECT sal*12+IFNULL(comm,0)*12 FROM emp WHERE job='副总';

---------------------------------------------------------------------

#1.null的数据用is/is not关键字来过滤

#练习1:查询没有奖金的员工信息

SELECT * FROM emp WHERE comm IS NULL;

#查询有奖金的员工

SELECT * FROM emp WHERE comm IS NOT NULL;

-----------------------------------------------------------------------

#2 between and

#练习:查询工资在5000~10000的员工信息

SELECT * FROM emp WHERE sal>=5000 AND sal <=10000;

SELECT * FROM emp WHERE sal BETWEEN 5000 AND 10000;# [5000,10000];

#查19年入职的员工姓名

SELECT ename FROM emp WHERE hiredate BETWEEN '2019-1-1' AND '2019-12-31';

SELECT ename FROM emp WHERE YEAR(hiredate)=2019;#同上

SELECT ename FROM emp WHERE YEAR(hiredate) BETWEEN 2019 AND 2019;#同上

-------------------------------------------------------------------------

#3 limit 数字1,数字2--分页,数字1是从下标开始展示,,数字2表示展示行数

#练习:展示前两条员工信息

SELECT * FROM emp LIMIT 2; #只取前n条的数据

SELECT * FROM emp LIMIT 1,4; #从1+1的数据开始,总共展示4条

#练习:查询岗位是员工的第一条记录

SELECT * FROM emp WHERE (job='员工') LIMIT 0,1 ;#limit 通常放最后

---------------------------------------------------------------------------

#4 order by 排序,默认是升序ASC,+desc为降序

#练习:按照工资排序

SELECT * FROM emp ORDER BY sal;#升序排序

SELECT * FROM emp ORDER BY sal DESC;#按数值降序排序

#练习:按照名字排序

SELECT * FROM emp ORDER BY ename DESC;#按字母降序

#练习:按照岗位排序

SELECT * FROM emp ORDER BY job ASC;#按汉字对应的编号升序

#练习:查询15年到19年入职的员工信息只取前两条,并按照工资升序排序

SELECT * FROM emp WHERE

YEAR(hiredate) BETWEEN 2015 AND 2019 #区间[2015,2019]

ORDER BY sal ASC #排序,默认的升序

LIMIT 2;#分页,只取前两条,通常放最后

--------------------------------------------------------------------------

#统计需求

#练习:统计每个员工的年薪

SELECT *,sal*12+IFNULL(comm,0)*12 FROM emp ;

#统计19年以前入职的员工信息

SELECT * FROM emp WHERE YEAR(hiredate)<2019;

--------------------------------------------------------------------------

#聚合函数max min sum avg count

#练习1:求最高薪的员工信息

SELECT MAX(sal) FROM emp;

#求员工的最低薪,总和,平均数,记录总数

SELECT MIN(sal) FROM emp;#最小值

SELECT SUM(sal) FROM emp;#总和

SELECT AVG(sal) FROM emp;#平均数

      #最大值  #最小值  #平和     #平均数  

SELECT MAX(sal),MIN(sal),SUM(sal),AVG(sal) FROM emp;

#员工表里一共有几条记录

SELECT COUNT(*) FROM emp;#低效

SELECT COUNT(1) FROM emp;#高效

SELECT COUNT(sal) FROM emp;#了解,不推荐

SELECT COUNT(comm) FROM emp;#按照字段统计师不统计null

---------------------------------------------------------------------------

#练习:统计名字里包含a的总数记录

SELECT COUNT(1) FROM emp WHERE ename LIKE '%a%'

#练习:统计19年入职的员工里的最高薪

SELECT MAX(sal) FROM emp WHERE YEAR(hiredate)=2019;

#练习:统计2号部门的平均薪资

SELECT AVG(sal)FROM emp WHERE deptno=2;

#练习:统计2号部门一年的工资支出

SELECT SUM(sal*12+IFNULL(comm,0)*12) FROM emp WHERE deptno = 2;#工资加奖金支出

SELECT SUM(sal)*12 FROM emp WHERE deptno = 2;#工资支出

----------------------------------------------------------------------------

#分组:使用关键字 group by

#练习:统计每个部门的平均薪资

SELECT AVG(sal),deptno FROM emp GROUP BY deptno;#混合查聚合列和非聚合列必须要分组

#练习:统计每个部门的最高薪资

#查询结果中出现了混合列,包裹着聚合列和非聚合列

SELECT MAX(sal),deptno FROM emp GROUP BY deptno;#分组口诀:通常按照非聚合列分组

#练习:统计每年入职的总人数

SELECT COUNT(1),YEAR(hiredate) FROM emp GROUP BY YEAR(hiredate);

#练习统计每个岗位的平均薪资

SELECT AVG(sal),job FROM emp GROUP BY job ;

#having 把分组后的数据还想继续过滤,

#练习统计每个岗位的平均薪资,而且只要>=10000的

SELECT AVG(sal),job FROM emp GROUP BY job HAVING AVG(sal)>=10000;

SELECT AVG(sal) AVG,job FROM emp GROUP BY job HAVING AVG>=10000;#同上,分组后的过滤,avg是别名

#SELECT AVG(sal) AVG,job FROM emp where AVG>=10000;#where里不能用别名,也不能出现聚合函数

#练习:统计每年入职的人数,并且只要19年的

SELECT COUNT(1),YEAR(hiredate) a FROM emp

WHERE YEAR(hiredate)=2019

GROUP BY YEAR(hiredate)=2019  #分组

#having a=2019;#分组后过滤

SELECT COUNT(1),YEAR(hiredate) a FROM emp WHERE YEAR(hiredate)=2019

#where having高效,因为执行时机早

#having 把分组后的数据还想继续过滤,

#练习统计每个岗位的平均薪资,而且只要>=10000的

SELECT AVG(sal),job FROM emp GROUP BY job HAVING AVG(sal)>=10000;

SELECT AVG(sal) AVG,job FROM emp GROUP BY job HAVING AVG>=10000;#同上,分组后的过滤,avg是别名

#SELECT AVG(sal) AVG,job FROM emp where AVG>=10000;#where里不能用别名,也不能出现

SELECT * FROM emp  ORDER BY sal DESC;

SELECT * FROM emp ORDER BY sal DESC,job ASC;

SELECT * FROM emp ORDER BY deptno DESC,job ASC;

SELECT COUNT(1) FROM emp WHERE ename LIKE '%a%';

#查询每个岗位的员工个人数

SELECT job,COUNT(*) FROM emp GROUP BY job;

#什么时候需要分组,查询时出现了混合列

#统计每个部门包含re的部门编号

SELECT deptno FROM dept WHERE dname LIKE 're%'

GROUP BY loc;

#统计每年入职的员工的最高薪资,只要>5000的

SELECT MAX(sal),YEAR(hiredate) FROM emp

GROUP BY YEAR(hiredate) #分组

#having里可以用聚合函数,where 不能

HAVING MAX(sal)>5000    #分组后过滤

#查询所有员工的最高薪-用分页

SELECT sal FROM emp ORDER BY sal DESC LIMIT 1

CREATE TABLE USER(

id INT(11) PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),pwd VARCHAR(10));

INSERT INTO USER VALUES(NULL,'jack',"123");

INSERT INTO USER VALUES(NULL,'rose',"456");

#对上面SQL中使用的事物进行优化,因为上面的SQL需要两个事物开启

#下面这种SQL也叫做批量插入的功能,高效,多次插入使用同一个事务

INSERT INTO USER VALUES(NULL,'tnoy',"123"),(NULL,'jerry',"456")

#默认约束:给字段设置默认值而不是null,使用default

CREATE TABLE a(

id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,

sex VARCHAR(10) DEFAULT '男')

#检查约束:使用check

CREATE TABLE b(

id INT PRIMARY KEY AUTO_INCREMENT,

age INT,

CHECK(age<100 AND age>0 OR ?)#了解,数据要满足检查条件才可以

)

#外键约束:

CREATE TABLE tb_user(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

age INT(3),

sex VARCHAR(10) DEFAULT '男'#默认约束

)

CREATE TABLE tb_user_address(

user_id INT PRIMARY KEY,

address VARCHAR(200),

#创建外键

#FOREIGN KEY(当前表主键名) REFERENCES 对方表(对方的主键)

FOREIGN KEY(user_id) REFERENCES tb_user(id)#创建外键

)

#使用外键

#约束的情况1:子表的主键值  必须 取自 主表的主键值

#约束的情况2:主表的记录,没有被子表使用,才可以删

#如果表存在就删除

DROP TABLE IF EXISTS courses;

DROP TABLE IF EXISTS scores;

DROP TABLE IF EXISTS students;

DROP TABLE IF EXISTS teachers;

#课程表

CREATE TABLE courses(

cno VARCHAR(5) NOT NULL,

cname VARCHAR(10) NOT NULL,

tno VARCHAR(3) NOT NULL,

PRIMARY KEY (cno)

);

#得分表

CREATE TABLE scores(

sno VARCHAR(3) NOT NULL,

cno VARCHAR(5) NOT NULL,

degree NUMERIC(10,1) NOT NULL,

PRIMARY KEY (sno, cno)

);

#学生表

CREATE TABLE students(

sno VARCHAR(3) NOT NULL,

sname VARCHAR(4) NOT NULL,

ssex VARCHAR(2) NOT NULL,

sbirthday DATETIME,

class VARCHAR(5),

PRIMARY KEY (sno)

);

#老师表

CREATE TABLE teachers(

tno VARCHAR(3) NOT NULL,

tname VARCHAR(4),

tsex VARCHAR(2),

tbirthday DATETIME,

prof VARCHAR(6),

depart VARCHAR(10),

PRIMARY KEY (tno)

);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (108 ,'曾华' ,'男' ,'1977-09-01',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (105 ,'匡明' ,'男' ,'1975-10-02',95031);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (107 ,'王丽' ,'女' ,'1976-01-23',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (101 ,'李军' ,'男' ,'1976-02-20',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (109 ,'王芳' ,'女' ,'1975-02-10',95031);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (103 ,'陆君' ,'男' ,'1974-06-03',95031);

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (804,'易天','男','1958-12-02','副教授','计算机系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (856,'王旭','男','1969-03-12','讲师','电子工程系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (825,'李萍','女','1972-05-05','助教','计算机系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (831,'陈冰','女','1977-08-14','助教','电子工程系');

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-105' ,'计算机导论',825);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-245' ,'操作系统' ,804);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('6-166' ,'模拟电路' ,856);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('6-106' ,'概率论' ,831);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('9-888' ,'高等数学' ,831);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-245',86);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-245',75);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-245',68);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-105',92);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-105',88);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-105',76);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'3-105',64);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'3-105',91);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'3-105',78);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'6-166',85);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'6-106',79);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'6-166',81);

#多表联查 三种方式

#方式一:笛卡尔积,用逗号隔开多张表

SELECT * FROM emp,dept;#产生了大量的结果集

#描述两张表的关系,表名.字段名

SELECT * FROM emp,dept WHERE dept.deptno=emp.deptno;#描述两张表的关系

#练习:查询部门表的部门名称,展示员工表所有数据

SELECT emp.*,dept.dname FROM dept,emp WHERE dept.deptno= emp.deptno

#练习:查询部门的所有成员和员工的名字,但是不要部门名称叫accounting的数据

SELECT dept.*,emp.ename FROM dept,emp#逗号隔开表名

WHERE dept.deptno=emp.deptno #表关系

AND dept.dname='accounting';#业务条件

#练习:查询所有数据,条件是部门编号>1的

SELECT dept.*,emp.* FROM dept,emp

WHERE dept.deptno=emp.deptno

AND emp.deptno>1

#练习:查询易天老师能讲的课程名称

SELECT courses.cname FROM teachers,courses

WHERE courses.tno=teachers.tno

AND teachers.tname='易天';

#练习:查询计算机导论课程的总分

SELECT SUM(degree) FROM courses,scores

WHERE courses.cno=scores.cno

AND courses.cname='计算机导论'

#方式二:连接查询,用join连接多张表 on后面是条件

SELECT * FROM dept JOIN emp;#jpin连接多张表

SELECT * FROM dept JOIN emp

ON dept.deptno=emp.deptno#表关系

#练习:查询部门名称和员工表的所有数据

SELECT dept.dname,emp.* FROM dept JOIN emp

ON dept.deptno=emp.deptno#表关系 

#练习:查询部门的所有成员和员工的名字,但是不要部门名称叫accounting的数据

SELECT dept.*,emp.ename FROM dept JOIN emp

ON dept.deptno=emp.deptno #表关系

WHERE dept.dname='accounting' #业务条件

#练习:查询所有部门和员工数据,条件是部门编号>1的

SELECT * FROM dept JOIN emp

ON dept.deptno=emp.deptno

WHERE dept.deptno>1

#练习:查询易天老师能讲的课程名称

SELECT courses.cname FROM courses JOIN teachers

ON courses.tno=teachers.tno

WHERE teachers.tname='易天'

#练习:查询计算机导论课程的总分

SELECT SUM(scores.degree) FROM courses JOIN scores

NO courses.cno=scores.cno

WHERE courses.cname='计算机导论'

#测试三种连接的区别

#有两种连接查询:内连接和外连接(左外连接,右外连接)

#innerjoin:查两张表的交集

#leftjoin:左边表的所有和左边满足条件的

#reght join:右边表的所有和左边满足条件的

#内连接:取交集,取左右表都满足条件的

SELECT * FROM dept INNER JOIN emp

ON dept.deptno=emp.deptno#取交集

#左外连接:取左表的所有和右表满足条件的不满足的都是null

SELECT * FROM dept LEFT JOIN emp

ON dept.deptno=emp.deptno

#右外连接:取右表的所有和左表满足条件的不满足的都是null

SELECT * FROM emp RIGHT JOIN dept

ON dept.deptno=emp.deptno

#连接查询的效率:小表驱动大表

#把结构简单或者数据量勺的表放在前面作为左表

#因为左表会查所有数据,右表只查满足了条件的那些数据

你可能感兴趣的:(sql,数据库,database)