SQL语句汇总
SQL语句汇总
"SQL"是 "Structured Query Language" 即“结构化查询语言”的简称,它是用来管理关系型数据库的。
其包括:数据定义语言(DDL)数据查询语言(DQL)数据操作语言(DML)数据控制语言(DCL)
聚合函数、分组、子查询及组合查询
聚合函数:统计行数量(COUNT)、获取单个列的合计值(SUM)、计算某个列的平均值(AVG)、计算列的最大值(MAX)、计算列的最小值(MIN)
SQL的执行顺序:
CREATE DATABASE 数据库名;
CREATE DATABASE test_sql
此图为SQLyog的左侧目录栏,前三个为本地自带数据库。将SQL语句全部选中运行(F8)后,F5刷新目录栏,出现了我们创建的数据库。
USE test_sql;
接下来就开始创建表了,在创建表之前先列出几种常用的数据类型
整数数据类型:
-INT 大小:4字节
-BIGINT 大小:8字节
浮点数据类型:
- FLOAT 大小:4字节 精度:7位小数
- DOUBLE 大小:8字节 精度:15位小数
字符串数据类型:
- VARCHAR 范围:0-65535
日期数据类型:
- DATE 大小:3字节 格式:YYYY
- DATETIME 大小:8字节 格式:YYYY-MM-DD
创建表:
CREATE TABLE <表名> (<列名> <列的数据类型> [<列的约束>]);
示例:
CREATE TABLE t_student( student_name VARCHAR(10), student_birthday DATETIME, student_phone INT, student_score FLOAT);
上表中我们创建了一张学生表,并定义了姓名、生日、电话、得分四列,列名后加上数据类型。其中要注意的是VARCHAR需要在括号内设置字符串的最大长度。
刷新之后就可以看到我们创建的数据库中多了一张表:
选择打开表可以直观的看到内容:
之后我们可以通过SQL语句也可以通过手动为表添加内容。
CREATE TABLE copy_student SELECT * FROM t_student;
如此我们便复制了一张名为copy_student的表,它包括t_student表中的内容与结构。注意:复制表的同时表的约束并不能复制过来。
添加新列:
ALTER TABLE t_student ADD student_address VARCHAR(50);
更改列:
ALTER TABLE t_student CHANGE student_birthday student_age INT;
这里我们把学生生日列改为学生年龄列,CHANGE后第一个为旧列名,第二个为新列名。
删除列:
ALTER TABLE t_student DROP COLUMN student_score;
保证数据库的完整性是为了防止垃圾数据的产生,以免影响数据库的执行效率。这里简要说一些,因为毕竟不是理论类的文章,这里主要是整理汇总SQL语句。
分类:
CREATE TABLE t_student( student_id INT PRIMARY KEY, student_name VARCHAR(10), student_birthday DATETIME, student_phone INT, student_score FLOAT);
UNIQUE
唯一约束是指给定列的值必须唯一,与主键约束不同的是它可以为空。通常加在表中不能重复的信息中,如电话号码。
CREATE TABLE t_student( student_id INT PRIMARY KEY, student_name VARCHAR(10), student_birthday DATETIME, student_phone INT UNIQUE, student_score FLOAT);
NOT NULL
非空约束可以加在诸如姓名等列上。
CREATE TABLE t_student( student_id INT PRIMARY KEY, student_name VARCHAR(10) NOT NULL, student_birthday DATETIME, student_phone INT UNIQUE, student_score FLOAT);
设定默认值后,可以在添加此列时不指定值,数据库会自动填充设定的默认值。
DEFAULT
现给学生表加入性别列,默认值设为“男”,这样添加新的学生信息时如果没有填写具体的性别均会默认为男性:
CREATE TABLE t_student( student_id INT PRIMARY KEY, student_name VARCHAR(10) NOT NULL, student_sex VARCHAR(5) DEFAULT '男', student_birthday DATETIME, student_phone INT UNIQUE, student_score FLOAT);
外键约束是指在外键关联主键上强制加上一个约束,如果违反该约束,则不允许该条数据的修改。
创建主表--班级表:
CREATE TABLE t_class( class_id INT PRIMARY KEY, class_name VARCHAR(20) UNIQUE NOT NULL); )
创建从表--学生表,并设置外键约束:
CREATE TABLE t_student( student_id INT PRIMARY KEY, s_c_id INT REFERENCES t_class(class_id), student_name VARCHAR(10) NOT NULL, student_sex VARCHAR(5) DEFAULT '男', student_birthday DATETIME, student_phone INT UNIQUE, student_score FLOAT CONSTRAINT FOREIGN KEY(s_c_id) REFERENCES t_class(class_id);
红色标识的就是创建外键约束的方法,个人认为也是SQL语句中最难记的。
INSERT INTO <表名> (<列名列表>) VALUES (<值列表>)
如:
INSERT INTO t_student (student_id,student_name,student_age,student_sex) VALUES (1,'大毛',18,'男');
其中列名可以省略,省略之后要求插入的值必须与列一一对应:
INSERT INTO t_student VALUES (2,'王二',20,'男');
多行数据添加:
INSERT INTO t_student VALUES (3,'张三',22,'男'), (4,'李四',17,'女'), (5,'王五',23,'男');
假如要修改李四的年龄为21岁
UPDATE t_student SET student_age=21 WHERE student_name='李四';
注:修改多个列的值时用逗号隔开。要想设置某一列的值为空,只需让<列名>=NULL 即可。WHERE表示过滤条件。
现要删除20到22岁的学生信息:
DELETE FROM t_student WHERE student_age BETWEEN 20 AND 22;
WHERE的判断条件之后会更详细的介绍。
删除除了DELETE还有一种方法TRUNCATE,写法:
TRUNCATE TABLE 表名
二者区别在于:
分类:
多个列中间用逗号隔开,如果选择所有列可以用*号简写。
还是此表:
现在只想要查看姓名和年龄列:
SELECT student_name,student_age FROM t_student;
注意这里不是把其他列删除了,而是只显示我们想看见的部分。
SELECT CONCAT(student_name,'——',student_age) '组合值' FROM t_student;
CONCAT,可以将列与列之间用想要的符号连接起来:
排除重复——DISTINCT
现给原表加入一班级列:
按照之前方法查询班级列得到:
但是我们只想查看具体有哪些班级,这里就需要用到去重,也就是DISTINCT。
SELECT DISTINCT student_class FROM t_student;
返回限定行数的查询——LIMIT
LIMIT后面参数为1或2个:
LIMIT N 表示从第一行开始返回N行结果,LIMIT i,N 表示从第i+1行开始返回N行结果。
例:
SELECT * FROM t_student LIMIT 3;
SELECT * FROM t_student LIMIT 2,3;
*注:LIMIT很重要,它是之后做数据表格分页的关键。
分为单条件选择与多条件选择
单条件选择标准结构:
SELECT 列1, 列2 FROM 表名 WHERE 列3 = 值
关系运算符包括:> >= < <= = !=
多条件选择标准结构:
SELECT 列A, 列B FROM 表 WHERE 条件1 (AND或者OR) 条件2
其中AND表示并且,OR表示或者。
选择范围——BETWEEN
如:
SELECT * FROM t_student WHERE student_age BETWEEN 20 AND 23;
BETWEEN后的值为从下限到上限。
定义集合——IN或NOT IN
现在想查看年龄为17、20、23的学生信息:
SELECT * FROM t_student WHERE student_age IN (17,20,23);
反之NOT IN就是选择不包括在集合里的学生信息。
模糊查询——LIKE
为了更好的解释模糊查询,这里重新建张表:
这里姓王的兄弟们躺枪...别介意。
首先先说下占位符与通配符:
占位符 "_",表示任何单个字符。
通配符 "%",表示包含零或多个字符。
下面就来用模糊查询逐一选中我们想要的行。
名字只有两个字的:
SELECT * FROM t_student WHERE student_name LIKE '__';
这里可能看不清,引号里实际是两个占位符。
所有姓王的:
SELECT * FROM t_student WHERE student_name LIKE '王%';
最后一个字是“王”的:
SELECT * FROM t_student WHERE student_name LIKE '%王';
只要是名字中有“王”字的:
SELECT * FROM t_student WHERE student_name LIKE '%王%';
这下模糊查询就很明白了吧,当然还有其他组合,大家可以自己尝试。
处理空值数据:
判断条件不能用列名=NULL,而是要用IS NULL或IS NOT NULL。
标准写法:
SELECT * FROM t_student WHERE 性别 IS NULL
使用ORDER BY时,列名上指定ASC或DESC。ASC表示正序,DESC表示倒序。如果不指定则默认为正序。
按年龄排:
SELECT * FROM t_student ORDER BY student_age ASC;
SELECT * FROM t_student ORDER BY student_age DESC;
最后一定要注意!
基本查询SQL的执行顺序:
1.执行FROM 2.WHERE条件过滤 3.SELECT投影 4.ORDER BY排序
SELECT COUNT(<计数规范>) FROM <表名>
其中,计数规范包括:
- * :计数所有选择的行,包括NULL值;
- ALL 列名:计数指定列的所有非空值行,如果不写,默认为ALL;
- DISTINCT 列名:计数指定列的唯一非空值行。
SELECT COUNT(*) FROM t_student;
也可加入筛选条件,如求女学生数目:
SELECT COUNT(*) FROM t_student WHERE student_sex='女';
SELECT COUNT(DISTINCT student_class) FROM t_student;
计算学生平均年龄:
SELECT AVG(student_age)FROM t_student;
求年龄最大的学生信息(最小值同理):
SELECT MAX(student_age) FROM t_student;
注:这里只能求出最大年龄,要想显示年龄最大的学生全部信息,需要用到之后的子查询。
SQL中数据可以按列名分组,搭配聚合函数十分实用。
例,统计每个班的人数:
SELECT student_class,COUNT(ALL student_name) AS 总人数 FROM t_student GROUP BY (student_class);
AS为定义别名,别名的使用在组合及联接查询时会有很好的效果,之后再说。
分组中也可以加入筛选条件WHERE,不过这里一定要注意的是,执行顺序为:WHERE过滤→分组→聚合函数。牢记!
统计每个班上20岁以上的学生人数:
SELECT student_class,COUNT(student_name) AS 总人数 FROM t_student WHERE student_age >20 GROUP BY (student_class);
之前说了分组操作、聚合函数、WHERE过滤的执行顺序,那如果我们希望在聚合之后执行过滤条件怎么办?
例,我们想查询平均年龄在20岁以上的班级
能用下面的语句吗?
SELECT student_class, AVG(student_age) FROM t_student WHERE AVG(student_age)>20 GROUP BY student_class;
SELECT student_class,AVG(student_age) AS 平均年龄 FROM t_student GROUP BY (student_class) HAVING AVG(student_age)>20;
SELECT s.student_id,s.student_name,(SELECT class_name FROM t_class c WHERE c.class_id=s.class_id) FROM t_student s GROUP BY s.student_id;
* 首先这条SQL语句用到了别名,写法为在FORM的表名后加上某个字符比如FROM t_student s,这样在之后调用t_student的某一列时就可以用s.student_id来强调此列来源于对应别名的那张表。
别名在子查询及联接查询中的应用有着很好效果,当两张表有相同列名或者为了加强可读性,给表加上不同的别名,就能很好的区分哪些列属于哪张表。
还有种情况就是在子查询或联接查询时,主查询及子查询均为对同一张表进行操作,为主、子查询中的表加上不同的别名能够很好的区分哪些列的操作是在主查询中进行的,哪些列的操作是在子查询中进行的,下文会有实例说明。
SELECT * FROM t_student WHERE student_subject='C语言' AND student_score>=ALL (SELECT student_score FROM t_student WHERE student_subject='C语言') ;
结果:
SELECT * FROM t_student WHERE student_subject='C语言' AND student_score >(
SELECT student_score FROM t_student WHERE student_name='李四' AND student_subject='C语言');
通过上面两例,应该可以明白子查询在WHERE中嵌套的作用。通过子查询中返回的列值来作为比较对象,在WHERE中运用不同的比较运算符来对其进行比较,从而得到结果。
现在我们回到最开始的问题,怎么查出每门课最高成绩的学生的信息:
SELECT * FROM t_student s1 WHERE s1.student_score >= ALL(SELECT s2.student_score FROM t_student s2 WHERE s1.`student_subject`=s2.student_subject);
这里就是上文提到的别名的第二种用法,主、子查询对同一张表操作,区分开位于内外表中相同的列名。
结果:
通过UNION运算符来将两张表纵向联接,基本方式为:
SELECT 列1 , 列2 FROM 表1 UNION SELECT 列3 , 列4 FROM 表2;
UNION ALL为保留重复行:
SELECT 列1 , 列2 FROM 表1 UNION ALL SELECT 列3 , 列4 FROM 表2;
相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需要用到表联接。
和之前的UNION组合查询不同,UNION是将不同的表组合起来,也就是纵向联接,说白了就是竖着拼起来。
而表联接是通过笛卡尔乘积将表进行横向联接,所谓的通过笛卡尔乘积简单说就是两表的行依次相联再相加。要想更详细的理解可以百度下,毕竟本文主要是汇总SQL语句。
现在有如下两张表:
这是当初老师布置的一份作业,我偷个懒就不改数据了。不过把这些真神级人物的大名贴出来做“实验”总觉得心里有很虚,更何况大部分都是IT业的。如有什么不敬我先道个歉,别跟我一般见识。
好了,扯远了。怎么联接这两张表呢?标准写法:
SELECT * FROM t_student JOIN t_class
结果这里只截一小部分图,因为笛卡尔乘积后的行数等于两张表的行数乘积,实在太多了。
这里就可以理解表联接的原理了,依次相连再相加。当然其中很多是无效行,为了去除无效的行我们就要用到外键来进行约束。学生表中的_fk与班级表中的_infor相关联:
SELECT * FROM t_student s JOIN t_class c ON s._fk=c._infor;
结果:
这里通过外键的匹配我们就得到了一张完美的联接之后的表,它可以看做一张新表,想要任何数据均可以从此表中查询,这就是表联接的强大之处。
表联接的分类:
内联接:
内联接是指两个表中某一行相关的列值匹配时,这一行才会出现在表中。就像上例中s._fk与c._infor相同时才会出行该行,其他的行剔除。
语法为INNER JOIN 其中INNER可以省略。
内联接的简写:
SELECT * FROM t_student s,t_class c WHERE c._infor = s._fk
* 此写法也是我们用的最多的。
外联接:
分为左外联接与右处联接。
SELECT * FROM t_student s RIGHT JOIN t_class c ON s._fk=c._infor;
上面SQL中表t_class在写在JOIN的右边,所以我们用RIGHT JOIN来进行外联接。
最下面多了一行四班的信息
例如我们想查出还没有学生录入的班级信息:
SELECT c._id,c._cname,c._code FROM t_student s RIGHT JOIN t_class c ON s._fk=c._infor WHERE s._id IS NULL;
这就是外联接的用法,通常用在我们想要的数据匹配不上时。
自联接:
自联接属于内联接或外联接的一种特例,自联接所联接的表均是来自同一张,用法个人感觉还是比较巧妙的。
现有一表如下:
表中,6个人均属于某公司的员工。区别是李四为张三和王五的领导,张八为赵六和孙七的领导。leader_id与work_id相关联。
现在可以通过自联接巧妙的将一张表分为员工部分和领导部分:
SELECT w.work_name,l.work_name 领导姓名 FROM t_emp w,t_emp l WHERE w.leader_id=l.work_id;
注意别名的用法
结果: