@@ -13,7 +13,7 @@ SQL (Structured Query Language) 是关系数据库最重要的操作语言,且
1313
1414SQL 命令一般分为 DQL、DML、DDL 三类:
1515
16- - DQL: 数据查询语句,基本就是 SELECT 查询命令,用于数据查询。
16+ - DQL: Data Query Language 数据查询语句,基本就是 SELECT 查询命令,用于数据查询。
1717
1818- DML: Data Manipulation Language 数据操纵语言,主要用于插入、更新、删除数据,即 INSERT、UPDATE、DELETE 三类。
1919
@@ -216,3 +216,277 @@ ORDER BY 需要在 WHERE 语句之后,若顺序不对会报错。
216216``` SQL
217217SELECT * FROM student WHERE age >= 15 ORDER BY age;
218218```
219+
220+ 还可以对多个查询结果排序
221+
222+ ``` SQL
223+ SELECT * FROM student ORDER BY age, student_name;
224+ ```
225+
226+ 后面加上 DESC 开逆序
227+
228+ ``` SQL
229+ SELECT * FROM student ORDER BY age DESC ;
230+ SELECT * FROM student ORDER BY age DESC , student_name;
231+ ```
232+
233+ ### 分组查询
234+
235+ 例如要统计不同年龄段的学生人数,可以使用分组查询
236+
237+ ``` SQL
238+ # SELECT age, count(*) FROM student GROUP BY age;
239+
240+ age | count
241+ -- ---+-------
242+ 15 | 2
243+ 14 | 1
244+ ```
245+
246+ 注意,使用 GROUP BY 语句时需要使用聚合函数,常见的有 count、sum 等
247+
248+ ### 多表关联查询
249+
250+ 多表关联查询也称表 join,例如有一张 class 班级表,建表语句如下
251+
252+ ``` SQL
253+ CREATE TABLE class (no int primary key , class_name varchar (40 ));
254+ ```
255+
256+ 插入一些测试数据
257+
258+ ``` SQL
259+ # INSERT INTO class VALUES(1, '初二(1)班');
260+ # INSERT INTO class VALUES(2, '初二(2)班');
261+ # INSERT INTO class VALUES(3, '初二(3)班');
262+ # INSERT INTO class VALUES(4, '初二(4)班');
263+
264+ # SELECT * FROM class;
265+ no | class_name
266+ -- --+-------------
267+ 1 | 初二(1 )班
268+ 2 | 初二(2 )班
269+ 3 | 初二(3 )班
270+ 4 | 初二(4 )班
271+ (4 rows)
272+ ```
273+
274+ 还有一张学生表 student,建表语句如下
275+
276+ ``` SQL
277+ CREATE TABLE student (no int primary key , student_name varchar (40 ), age int , class_no int );
278+ ```
279+
280+ 同样插入一些数据
281+
282+ ```
283+ # SELECT * FROM student;
284+ no | student_name | age | class_no
285+ ----+--------------+-----+----------
286+ 1 | 张三 | 14 | 1
287+ 2 | 吴二 | 15 | 1
288+ 3 | 李四 | 13 | 2
289+ 4 | 吴三 | 15 | 2
290+ 5 | 王二 | 15 | 3
291+ 6 | 李三 | 14 | 3
292+ 7 | 吴二 | 14 | 3
293+ 8 | 张四 | 14 | 4
294+ ```
295+
296+ 假如想要查询每个学生名字与班级名称之间的关系,就需要关联查询两张表
297+
298+ ``` SQL
299+ # SELECT student_name, class_name FROM student, class
300+ WHERE student .class_no = class .no ;
301+
302+ student_name | class_name
303+ -- ------------+-------------
304+ 张三 | 初二(1 )班
305+ 吴二 | 初二(1 )班
306+ 李四 | 初二(2 )班
307+ 吴三 | 初二(2 )班
308+ 王二 | 初二(3 )班
309+ 李三 | 初二(3 )班
310+ 吴二 | 初二(3 )班
311+ 张四 | 初二(4 )班
312+ (8 rows)
313+ ```
314+
315+ 关联查询就是在 WHERE 子句中加上需要关联的条件 ` WHERE student.class_no = class.no; `
316+
317+ 由于两张表中有些列的名称相同,例如 student 中的 no 是学生编号,class 中的 no 是班级编号,所以关键条件中要明确使用 ` 表名.列名 ` 来明确唯一定位某一列
318+
319+ ``` SQL
320+ SELECT student_name, class_name FROM student a, class b
321+ WHERE a .class_no = b .no ;
322+ ```
323+
324+ 还可以在关联查询的 WHERE 子句中加上其他过滤条件
325+
326+ ``` SQL
327+ SELECT student_name, class_name FROM student a, class b
328+ WHERE a .class_no = b .no
329+ AND age > 14 ;
330+ ```
331+
332+ ### 子查询
333+
334+ 当一个查询是另一个查询的条件时,称为子查询。
335+
336+ 主要有 4 种语法的子查询:
337+
338+ - 带有谓词 IN 的子查询: ` expression [NOT] in (sqlstatement) `
339+ - 带有谓词 EXISTS 的子查询: ` [NOT] EXISTS (sqlstatement) `
340+ - 带有比较运算符的子查询: ` comparsion(>,<,=,!=) (sqlstatement) `
341+ - 带有 ANY (SOME) 或 ALL 谓词的子查询: ` comparsion [ANY|ALL|SOME] (sqlstatement) `
342+
343+ 下面仍然使用 class 和 student 两个表来做示例
344+
345+ - 使用带有谓词 IN 的子查询来查询 “初二(1)班” 的学生记录
346+
347+ ``` SQL
348+ SELECT * FROM student
349+ WHRER class_no IN (
350+ SELECT no FROM class
351+ WHERE class_name= ' 初二(1)班'
352+ );
353+ ```
354+
355+ 查询结果如下
356+
357+ ``` SQL
358+ no | student_name | age | class_no
359+ -- --+--------------+-----+----------
360+ 1 | 张三 | 14 | 1
361+ 2 | 吴二 | 15 | 1
362+ (2 rows)
363+ ```
364+
365+ - 同样可以使用带 EXISTS 谓词的子查询实现
366+
367+ ``` SQL
368+ SELECT * FROM student s
369+ WHERE EXISTS (
370+ SELECT 1 FROM class c
371+ WHERE s .class_no = c .no
372+ AND c .class_name = ' 初二(1)班'
373+ );
374+ ```
375+
376+ EXISTS 是一个存在性测试,它检查子查询是否返回至少一行数据,执行逻辑如下:
377+
378+ 1 . 对于每个学生记录,数据库会执行一次子查询
379+ 2 . 子查询检查:class 表中查找匹配 WHERE 规则的记录
380+ 3 . 返回判断:如果查询找到匹配,EXISTS 为 True,则结果包含该学生,否则为 False 不包含
381+
382+ 上面查询使用 SELECT 1 是因为只关系是否有返回值,而不关系返回值的类型
383+
384+ - 还可以使用带有比较符的子查询实现
385+
386+ ``` SQL
387+ SELECT * FROM student
388+ WHERE class_no = (
389+ SELECT no FROM calss c
390+ WHERE class_name = ' 初二(1)班'
391+ );
392+ ```
393+
394+ - 还可以使用带 ANY (SOME) 或 ANY 谓词的子查询来实现
395+
396+ ``` SQL
397+ SELECT * FROM student
398+ WHERE class_no = ANY(
399+ SELECT no FROM class c
400+ WHERE class_name = ' 初二(1)班'
401+ );
402+ ```
403+
404+ - 如果要查询* 两个* 班级的学生记录,则不能使用带有等于 “=” 比较符的子查询
405+
406+ ``` SQL
407+ SELECT * FROM student
408+ WHERE no = (
409+ SELECT no FROM class c
410+ WHERE class_name in (' 初二(1)班' , ' 初二(2)班' )
411+ );
412+
413+ ERROR: more than one row returned by a subquery used as an expression
414+ ```
415+
416+ 上面报错说子查询不能返回多行,这种操作就是在说“找出学号等于(初二1班或初二2班的班级号)的学生“,但是等于号不能等于两个东西,只能等于一个东西,逻辑就错误了。
417+
418+ 这种不能返回多行的子查询也叫* 标量子查询* ,标量子查询不仅能嵌套在 WHERE 子句中,也可以嵌套在 SELECT 的列表中。
419+
420+ 如果要查询每个班级学生的最大年龄,可以使用下面 SQL 语句:
421+
422+ ``` SQL
423+ SELECT no, class_name, (
424+ SELECT max (age) AS max_age
425+ FROM student s WHERE s .no = c .no
426+ ) AS max_age FROM class c;
427+ ```
428+
429+ 查询两个班级学生信息的时候,用带有 ANY (SOME) 谓词的子查询就没问题了,AYN 就是说只要等于里面任何* 一个* 就行。
430+
431+ ``` SQL
432+ SELECT * FROM student
433+ WHERE class_no = ANY(
434+ SELECT no FROM class c
435+ WHERE calss_name in (' 初一(1)班' , ' 初二(2)班' )
436+ );
437+ ```
438+
439+ ## 其他 SQL 语句
440+
441+ ### INSERT ... SELECT 语句
442+
443+ 使用 INSERT ... SELECT 语句可以将一张表中的数据插入另一张表中,属于 DML 语句。
444+
445+ 假设创建一张学生表的备用表 student_bak,建表语句如下:
446+
447+ ``` SQL
448+ CREATE TABLE student_bak (
449+ no int primary key ,
450+ student_name varchar (40 ),
451+ age int ,
452+ class_no int
453+ );
454+ ```
455+
456+ 可以使用下面语句将 student 备份到备份表中
457+
458+ ``` SQl
459+ INSERT INTO student_bak SELECT * FROM student;
460+ ```
461+
462+ ### UNION 语句
463+
464+ 使用 UNION 语句可以把从两张表中查询出来的数据合在一个结果集下
465+
466+ ``` SQL
467+ SELECT * FROM student WHERE no = 1
468+ UNION
469+ SELECT * FROM student_bak WHERE no = 2 ;
470+ ```
471+
472+ 要注意的是,UNION 语句会将结果相同的两条记录合并成一条。
473+ 如果不想合并相同记录,可以使用 UNION ALL 语句。
474+
475+ ``` SQl
476+ SELECT * FROM student WHERE no = 1
477+ UNION ALL
478+ SELECT * FROM student_bak WHERE no = 1 ;
479+ ```
480+
481+ ### TRUNCATE TABLE 语句
482+
483+ TRUNCATE TABLE 语句作用是清空表内容,不含 WHERE 条件的 DELETE 语句(` DELETE FROM table_name ` )也可以情况表内容,但两者实现原理不同。
484+
485+ - TRUNCATE TABLE 是 DDL 数据定义语句,相当于重新定义一个新的表的方法,把原来表内容直接丢弃了,执行速度快
486+ - DELETE FROM 是 DML 数据操作语句,可以认为是一行一行地删除,执行速度较慢
487+
488+ ## Summary 总结
489+
490+ 从上面内容可以看出来,SQL是一种声明式编程语言,与命令式编程语言有较大的差异。
491+ 声明式编程语言主要是描述用户需要做什么,需要得到什么结果,不像命令式编辑语言需要描述怎么做,过程是什么。
492+ SQL语句能智能地实现用户的需要,而不需要用户关心具体的运行过程。
0 commit comments