初学者使用sql时易犯的错误(持续更新)

DDL(数据定义)

DROP 子句 用于删除指定的列名,
若选择RESTRICT ,则删除的基本表不能被其他表的约
束所引用(如 CHECK FOREIGN KEY 等约束),不
能有视图,不能有触发器,不能有存储过程或函数等。
如果存在这些依赖该表的对象,则此表不能被删除。
若选择 CASCADE ,则该表的删除没有限制条件。在删
除基本表的同时,相关的依赖对象,例如视图等都将被
一起删除。
一般在缺省情况下默认为 RESTRICT 与具体实现有关

DML(数据操作)

一。插入

INSERT INTO < 表名 > [(< 属性列 1>[,< 属性列 2 > ... )]
VALUES (< 常量 1> [ < 常量 2>] ...
);
INTO 子句
指定要插入数据的表名及属性列
属性列的顺序可以与表定义中的顺序不一致
没有指定属性列 :表示要插入的是一条完整的元组,
且属性列属性与表定义中的顺序一致
指定部分属性列:插入的元组在其余属性列上取空
值或者是默认值
VALUES 子句
提供的值必须与 INTO 子句匹配:个数、顺序和值的
类型
【例】在学生表中插入一个学生元组,其学号为
101215 ,姓名为李斌,男, 19 岁,是计算机系
的学生。
INSERT INTO Student
VALUES( ' 101215 ' , ' 李斌' , '男' ,19, '计算机' );
INSERT INTO Student ( Sno, Sname, Sdept, Sage, Ssex )
VALUES( ' 101215 ' , ' 李斌' , '计算机' ,19, '男' );
将子查询结果插入指定表中
INSERT INTO < 表名 >[(< 列名 1>[,< 列名 2>, ])]
<SELECT 语句 >; /* 子查询 */
INTO 子句
指定要插入数据的表名及属性列
属性列的顺序可与表定义中的顺序不一致
没有指定属性列,则表示插入一条完整的元组
指定部分属性列,则在其余属性列上取空值
子查询
SELECT 子句目标列必须与 INTO 子句匹配:个数、
顺序和值的类型
【例】计算计算机系每个学生的平均成绩,并保存
CS-AVG 表中。
1. 生成学生的平均成绩表CS-AVG
2. 在CS-AVG中插入计算机系学生的平均成绩
CREATE TABLE CS-AVG
( Sno CHAR(6)NOT NULL
Grade NUMBER(4,1));
INSERT INTO CS-AVG (Sno, Grade)
SELECT Sno, AVG(Grade) FROM SC
WHERE Sno IN (
SELECT Sno FROM Student
WHERE Sdept='CS')
GROUP BY Sno ;

二。更新与删除

DQL(数据查询)

一。注意DISTINCT短语的作用范围是所有目标列

错误的写法
SELECT DISTINCT Cno DISTINCT Grade
FROM SC;
正确的写法
SELECT DISTINCT Cno Grade
FROM SC;

二。空值查询:"IS NULL"不能用 "= NULL**"**代替

三。使用GROUP BY子句分组查询

细化聚集函数的作用对象
未对查询结果分组,聚集函数将作用于整个查询结果
对查询结果分组后,聚集函数将分别作用于每个组
分组方法
按指定的一列或多列值分组, 值相等的为一组
使用 GROUP BY 子句后, SELECT 子句的列名列
表中只能出现分组属性和聚集函数
GROUP BY 子句的作用对象是查询的中间结果表
【例】求各个课程号及相应的选课人数。
SELECT Cno COUNT(*) -- COUNT(Sno)
FROM SC
GROUP BY Cno
【例】查询选修了 3 门以上课程的学生学号
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*) >3
查询有 3 门以上课程是 90 分以上的学生的学
号及( 90 分以上的)课程数
SELECT Sno, COUNT(*)
FROM SC
WHERE Grade>=90
GROUP BY Sno
HAVING COUNT(*)>=3;

四。where与having的区别

  • WHERE 子句允许你指定过滤条件,这些条件基于表中的单个行。你不能在 WHERE 子句中使用聚合函数(如 SUM(), AVG(), COUNT(), 等)来过滤分组。
  • GROUP BY 子句通常与聚合函数一起使用,以计算每个组的汇总值。你不能在 GROUP BY 子句中指定单个行的条件,但可以在 HAVING 子句中这样做,HAVING 子句允许你基于聚合函数的结果来过滤分组。

五。连接查询

连接条件中各 连接字段 的类型必须是 可比的 ,但不必是
相同的

六。嵌套查询(又称子查询)

子查询的限制
不能使用 ORDER BY 子句
嵌套查询的分类与求解方法
不相关子查询
子查询的查询条件不依赖于父查询
由里向外逐层处理。每个子查询在上一级查询处理之前
求解,子查询的结果用于建立其父查询的查找条件。
相关子查询
子查询的查询条件依赖于父查询
先取外层查询中表的第一个元组,根据它与内层查询相
关的属性值处理内层查询,若 WHERE 子句返回值为真,
则取此元组放入结果表;然后再取外层表的下一个元组;
重复这一过程,直至外层表全部检查完为止
【例】找出每个学生所选修课程成绩超过该门课
程平均成绩的课程号。
SELECT Sno, Cno /* 外层查询 / 父查询 */
FROM SC x
WHERE Grade >=(SELECT AVG(Grade)
FROM SC y
WHERE y.Cno=x.Cno);
/* 内层查询 / 子查询 */
子查询不能在比较符之前
错误 的例子
SELECT Sno, Sname, Sdept
FROM Student
WHERE ( SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ' )
= Sdept
带有 ANY ALL 谓词的子查询
> ANY
大于子查询结果中的某个值
> ALL
大于子查询结果中的所有值
= ANY
等于子查询结果中的某个值
=ALL
等于子查询结果中的所有值(通常没有实际意义)
!= (或 <> ANY 不等于子查询结果中的某个值
!= (或 <> ALL
不等于子查询结果中的任何一个值
ANY ALL 谓词有时可以用聚集函数来实现
用聚集函数实现子查询通常比直接用 ANY ALL 查询效
率要高,因为前者通常能够减少比较次数。
【例】查询其他系中比 CS 任意一个 学生年龄小的
学生姓名和年龄
ANY 谓词实现
SELECT Sname, Sage
FROM Student
WHERE Sage < ANY (
SELECT Sage
FROM Student
WHERE Sdept= 'CS')
AND Sdept <> 'CS' ;
用聚集函数实现
SELECT Sname, Sage
FROM Student
WHERE Sage < (
SELECT MAX(Sage)
FROM Student
WHERE Sdept= 'CS')
AND Sdept <> 'CS' ;
带有 EXISTS 谓词的子查询
带有 EXISTS 谓词的子查询不返回任何数据,只产生逻
辑真值" true "或逻辑假值" false "。
若内层查询结果 非空 ,则返回 真值
若内层查询结果为空,则返回假值
EXISTS 引出的子查询,其目标列表达式通常用 * ,
为带 EXISTS 的子查询只返回真值或假值,给出列名无
实际意义
【例】查询所有选修了1号课程的学生姓名。
思路分析:在 Student 中依次取每个元组的 Sno值,用此
值去检查 SC 关系;若 SC 中存在这样的元组,其 Sno 值
等于此 Student.Sno 值,且Cno= ' 1 ' ,则取此
Student.Sname 送入结果关系
用嵌套查询
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno
AND Cno= ' 1 ')
所有 IN 谓词、比较运算符、 ANY ALL 谓词的子查询
都能用带 EXISTS 谓词的子查询等价替换。
带有 EXISTS 谓词的相关子查询只关心内层查询是否有
返回值,不需要查具体值,效率不低于相关子查询。
EXISTS/NOT EXISTS 实现全称量词
SQL 语言中没有全称量词 任取 For all
可以把带有全称量词的谓词转换为等价的带有存在量词
的谓词:
(任取 x)P ≡ 非 (存在 x( P))
】查询选修了全部课程的学生姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS #这样的课不存在
(SELECT *
FROM Course
WHERE NOT EXISTS #这门课他没选
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno))
EXISTS/NOT EXISTS 实现逻辑蕴函
SQL 语言中没有蕴函 (Implication) 逻辑运算
【例】查询至少选修了学生95001选修的全部课程的
学生的学号
解题思路:
用逻辑蕴函表达:查询学号为x的学生,对所有的课程y,
只要95001学生选修了课程y,则x也选修了y
变换后语义: 对于学生 x ,不存在这样的课程 y ,学生
95001选修了 y ,而学生 x 没有选
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno = '95001'
AND NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ .Sno= SCX. Sno AND
SCZ .Cno= SCY .Cno)) ;#一个表涉及多次查询时最好起别名,而且as是可以省略的

七。集合查询

并操作
语法形式
< 查询块 >
UNION [ALL]
< 查询块 >;
两个查询结果的属性列个数相同,对应项的数据
类型必须能够通过隐式转换相互兼容。
使用 UNION 合并多个结果集时,系统会 自动去掉
重复元组
使用 UNION ALL 操作符,可以保留重复元组
UNION 结果集中的列名与 UNION 运算中第一个
SELECT 语句的结果集中的列名相同,
其他的 SELECT 语句的结果集列名将被忽略。
差操作
标准 SQL 中没有提供集合差操作,但可用其他方
法间接实现。
【例】查询学生姓名与教师姓名的差集。 实际上是
查询学校中未与教师同名的学生姓名
SELECT DISTINCT Sname
FROM Student
WHERE Sname NOT IN
(SELECT Tname
FROM Teacher);
#另一种方式
SELECT Sname
FROM Student
EXCEPT
SELECT Tname
FROM Teacher;
对集合操作结果的排序
在执行集合操作时,默认按照最后结果表中第一
列数据的升序方式排列记录。
SELECT 子句不能含有 ORDER BY 子句,但是可
以将 ORDER BY 子句放在最后的 SELECT 语句后面,
以便对最后的结果表排序。
ORDER BY 子句只能用于对最终查询结果排序,
不能对中间结果排序。
任何情况下, ORDER BY 子句只能出现在最后。
对集合操作结果排序时, ORDER BY 子句中最好
用数字指定排序的列属性,以免出错
错误写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
ORDER BY Sno
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY Sno
正确写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY 1
基于派生表的查询
子查询出现在 FROM 子句中,这时子查询生成的
临时派生表( Derived Table )成为主查询的查询
对象
【例】找出每个学生超过他自己选修课程平均成绩
的课程号。
SELECT Sno, Cno
FROM SC, ( SELECT Sno, Avg(Grade) avg_grade
FROM SC
GROUP BY Sno ) AS Avg_sc
WHERE SC.Sno = Avg_sc.Sno
and SC.Grade >=Avg_sc.avg_grade;

约束

索引

在一个基本表上最多只能建立一个聚集索引
聚集索引可以包含多个列(组合索引)
聚集索引的适用范围
很少对基表进行增删操作
很少对其中的变长列进行修改操作

相关推荐
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO14 分钟前
MySQL事务
数据库·mysql
coderWangbuer23 分钟前
基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
spring boot·后端·sql
数据龙傲天1 小时前
1688商品API接口:电商数据自动化的新引擎
java·大数据·sql·mysql
engineer-gxd2 小时前
MySQL 表的操作
mysql
cyt涛2 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油2 小时前
01_SQLite
数据库·sqlite
liuxin334455663 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
与衫3 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
看山还是山,看水还是。3 小时前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec3 小时前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa