爆肝!一看就懂的《SQL 语言知识体系》【建议收藏】(中)

简介: 爆肝!一看就懂的《SQL 语言知识体系》【建议收藏】

爆肝!一看就懂的《SQL 语言知识体系》【建议收藏】(上):https://developer.aliyun.com/article/1529601

5. 数据操作

SQL 的数据操作包括 SELECT(查询)、INSERT(插入)、DELETE(删除)和 UPDATE(修改)四条语句。

5.1 SELECT 基本结构

数据库查询是数据库的核心操作,语法格式如下:

SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]...
FROM <表名或视图名>[,<表名或视图名>]
[WHERE <条件表达式>]
[GROUP BY <列名> [HAVING<条件表达式>]]
[ORDER BY <列名>[ASC|DESC]...]

SQL 查询中的子句顺序为SELECT、FROM、WHERE、GROUP BY、HAVING 和 ORDER BY。其中,SELECT、FROM 是必须的,HAVING 条件子句只能与 GROUP BY 搭配起来使用。


(1)SELECT 子句对应的是关系代数中的投影运算,用来列出查询结果中的属性。其输出可以是列名、表达式、函数集(AVG、COUNT、MAX、MIN、SUM),DISTINCT 选项可以保证查询的结果集不存在重复元组。


(2)FROM 子句对应的是关系代数中的笛卡尔积,它列出的表达式求值过程中需扫描的关系,即在 FROM 子句中出现多个基本表或视图时,系统首先执行笛卡尔积操作。


(3)WHERE 子句对应的是关系代数中的选择谓词。WHERE 子句的条件表达式可以使用的运算符如下:

5.2 简单查询

SQL 最简单的查询是找出关系中满足特定条件的元组,这些查询与关系代数中的选择操作类似,通常只需要使用三个关键字 SELECT、FROM 和 WHERE。

示例10. 查询所有员工信息;查询员工号为1088的员工的姓名和参加工作时间。

SELECT *
FROM 员工;

SELECT 姓名,参加工作时间
FROM 员工
WHERE 员工号 = 1088;

5.3 连接查询

如果查询涉及两个以上的表,则称为连接查询。

示例11. 关系模式:员工(员工号,姓名,性别,参加工作时间,部门号);部门(部门号,名称,电话,负责人);

# 查询部门名为“企业信息部”,且在2010年1月1日后入职的员工工号、姓名和性别
SELECT 员工号,姓名,性别
FROM 员工,部门
WHERE 员工.部门号 = 部门.部门号
AND 部门.名称 = '企业信息部'
AND 参加工作时间 > '2010-01-01';

连接查询相同字段需要带上表名点前缀,字符类型,日期类型的数据需要使用单引号。

5.4 子查询

子查询也称嵌套查询。嵌套查询是指一个 SELECT-FROM-WHERE 查询块可以嵌入另一个查询块之中。在 SQL 中允许多重嵌套。

示例12. 查询部门名为“企业信息部和行政部”,所有员工的工号、姓名和性别。

SELECT 员工号,姓名,性别
FROM 员工
WHERE 部门号 IN (SELECT 部门号
                FROM 部门
                WHERE 名称 IN ('企业信息部','行政部'));

5.5 聚集函数和更名操作

聚集函数是一个值的集合输入,返回单个值的函数。

SQL提供了5个预定义集函数:平均值AVG、最小值MIN、最大值MAX、求和SUM以及计数COUNT;


使用ANY和ALL谓词必须同时使用比较运算符,其含义及等价的转换关系如下:

使用聚合函数实现子查询比直接用 ALL 或 ANY 查询效率要高。

更名操作:SQL提供可为关系和属性重新命名的机制,可以使用 AS 来操作。as 子句可以出现在SELECT 子句中,也可出现在FROM子句中

示例13. 查询课程C1的最高分和最低分以及高低分之间的差距。

SELECT MAX(Grade) AS MAX_Grade
      ,MIN(Grade) AS MIN_Grade
      ,MAX(Grade)-MIN(Grade) AS GAP
FROM SC AS X
WHERE Cno='C1';

示例14. 查询其他系比计算机系CS所有学生年龄都要小的学生姓名及年龄。

## 方法一
SELECT Sname,Sage
FROM S 
WHERE Sage < ALL(SELECT Sage
                 FROM S
                 WHERE SD='CS')
      AND SD <> 'CS';
## 方法二    
SELECT Sname,Sage
FROM S
WHERE Sage < (SELECT MIN(Sage)
              FROM S 
              WHERE SD = 'CS')
      AND SD <> 'CS';

5.6 分组查询

在 WHERE 子句后面加上 GROUP BY 子句可以对元组进行分组,关键字 GROUP BY 后面跟着一个分组属性列表。如元组在分组后需要过滤,可以在后面加 HAVING 子句即可。

当元组含有空值时,应该记住以下两点:


(1)空值在任何聚集操作中都会被忽视。它对求和、求平均值和计数都没有影响。它也不能是某列的最大值或最小值。例如,COUNT(*)是某个关系中所有元组数目之和,但 COUNT(A) 却是A属性非空的元组个数之和。


(2)NULL 值又可以在分组属性中看作是一个一般的值。例如,SELECT A,AVG(B) FORM R 中,当A的属性值为空时,就会统计A=NULL的所有元组中B的均值。


示例15. 供应商数据库中的S、P、J、SPJ关系,查询某工程至少用了三家供应商(包含三家)供应的零件的平均数量,并按工程号的降序排列

SELECT Jno,AVG(QTY)
FROM SPJ 
GROUP BY Jno
HAVING COUNT(DISTINCT(Sno)) > 2
ORDER BY Jno DESC

5.7 字符串操作

谓词 LIKE 可以用来进行字符串匹配,通常也称模糊查询,语法格式如下:

[NOT] LIKE '<匹配串>'[ESCAPE'<换码字符>']

可以使用通配符%_,其中:%匹配任意字符串;_匹配任意一个字符。例如,_ _匹配只含两个字符的字符串;_ _ %匹配至少包含两个字符的字符串。

NULL 操作,通常使用 IS NULL、IS NOT NULL。

示例16. 学生关系模式为(Sno,Sname,Sex,SD,Sage,Addr),其中,Sno为学号,Same为姓名,Sex为性别,SD为所在系,Sage为年龄,Addr为家庭地址。请查询:

(1) 家庭地址包含“科技路”的学生姓名。

(2)名字为“晓军”的学生姓名、年龄和所在系。

# (1)
SELECT Sname FROM S WHERE Addr LIKE '%科技路%';
# (2)
SELECT Sname,Sage,SD FROM S WHERE Sname LIKE '_ _晓军';

为了使模式中包含特殊模式字符(即%和_),在SQL中允许使用 ESCAPE 关键词来定义转义符。转义字符紧靠着特殊字符,并放在它的前面,表示该特殊字符被当成普通字符。例如,在LIKE比较中使用ESCAPE关键词来定义转义符,例如使用反斜杠\作转义符。

LIKE 'ab\%cd%'ESCAPE '\',匹配所有以阿宝%cd开头的字符串。
LIKE 'ab\\cd%'ESCAPE '\',匹配所有以ab\cd开头的字符串。

5.8 集合操作

在关系代数中可以用集合的并、交和差来组合关系。SQL也提供了对应的操作,但是查询的结果必须具有相同的属性和类型列表。保留字UNION、INTERSECT和EXCEPT分别对应 和—。保留字用于两个查询时,应该将每个查询分别用括号括起来。

UNION 运算

示例17. 假设查询所有客户的集合的语句1为:SELECT Customer-no FROM depositor;查询有贷款客户的集合的语句2为:SELECT Customer-no FROM borrower。查询在银行有账户、有贷款或两者都有的所有客户身份证号。

# 1和2 取并集,使用 UNION 运算会自动去除重复
SELECT Customer-no FROM depositor
UNION 
SELECT Customer-no FROM borrower;
# 1和2 取并集,使用 UNION ALL 运算会保留重复
SELECT Customer-no FROM depositor
UNION ALL
SELECT Customer-no FROM borrower;

INTERSECT 运算

示例18. 学生关系模式为Students (Name, Sno, SEX, SD, Type, Address),教师关系模式为Teachers (Name, Eno, SEX, Salary, Address),查询是女研究生,又是教师且工资大于等于2600元的名字和地址。

(SELECT Name, Address 
 FROM Students
 WHERE SEX='女' 
       AND rype='研究生') 
INTERSECT
(SELECT Name, Address 
 FROM Teachers
 WHERE Salary>=2600);

EXCEPT 运算

示例19.查询不是教师的学生姓名。

(SELECT Name, Address FROM Students) 
 ЕХСЕРТ
(SELECT Name, Address FROM Teachers);

5.9 视图查询和更新

查询视图表时,系统先从数据字典中取出该视图的定义,然后将定义中的查询语句和对该视图的查询语句结合起来,形成一个修正的查询语句。

# 创建视图
CREATE VIEW V_ITEmp
AS SELECT 员工号,姓名,性别
   FROM 员工,部门
   WHERE 员工.部门号 = 部门.部门号
   AND 部门.名称 = 'IT部';
# 查询IT部性别为‘女’员工的姓名工号
SELECT 员工号,姓名
FROm V_ITEmp
WHERE 性别 = '女';

视图更新

SQL 对视图更新必须遵循以下规则:

(1) 从多个基本表通过连结操作导出的视图不允许更新。

(2) 对使用了分组、聚集函数操作的视图则不允许进行更新操作。

(3) 如果视图是从单个基本表通过投影、选取操作导出的则允许进行更新操作,且语法同基本表。

5.10 WITH 子句

With 子句是在SQL99中引入的,目前只有部分数据库支持这一子句。如果我们将一个复杂查询分解成一些小视图,然后将它们组合起来,就像将一个程序按其任务分解成一些过程一样,使得复杂查询的编写和理解都会简单得多。

示例20. 假定教师关系模式为Teachers(TName,Eno,Tdept,SEX,Salary,Address),利用With子句查询工资最高的教师姓名。此时,如果具有同样工资最高的教师有多个,他们都会被选择。

with max-Salary (value) AS (SELECT max (Salary)
FROM Teachers)
SELECT Tname
FROM Teachers, max-Salary
WHERE Teachers.Salary = max-Salary.value;

5.11 其他语句

插入语句语法如下:

INSERT INTO 表名(列名[,...n])
VALUES (常量[,...n]);

INSERT INTO 表名(列名[,...n])
SELECT 查询语句;

删除语句语法如下:

DELETE 
FROM 表名
WHERE 条件表达式;

更新语句语法如下:

UPDATE 表名
SET 列名=值表达式(,列名=值表达式)
[WHERE 条件表达式];

6. 数据控制

数据控制是控制用户对数据的操作和存储权力,是由 DBA 来决定的。DBMS 数据控制应具有如下功能:

(1)通过 GRANT 和 REVOKE 将授权通知系统,并存入数据字典。

(1)通过 GRANT 和 REVOKE 将授权通知系统,并存入数据字典。

(2)当用户提出请求时,根据授权情况检查是否执行操作请求。

SQL标准包括 DELETE、INSERT、SELECT 和 UPDATE 权限。SELECT 权限对应于 READ 权限,SQL 还包括了 REFERENCES 权限,用来限制用户在创建关系时定义外码的能力。

6.1 授权(GRANT)

授权语法格式:

GRANT <权限>[,<权限>]...
[ON<对象类型><对象名>]
TO <用户>[,<用户>]...
[WITH GRANT OPTION];

注意:若指定了 WITH GRANT OPTION 子句,那么获得了权限的用户还可以将权限赋给其他用户;接受权限的用户可以是单个或多个具体的用户,PUBLIC 参数可将权限赋给全体用户。不同类型的操作对象有不同的操作权限,常见的操作权限如下所示:

示例21. 如果用户要求把数据库SPJ中供应商S、零件P、项目J表赋予各种权限。各种授权要求如下:

(1) 将对供应商S、零件P、项目J的所有操作权限赋给用户 USER1 及 USER2。

(2) 将对供应商S的插入权限赋给用户 USER1,并允许将此权限赋给其他用户。

(3) DBA 把数据库 SPJ 中建立表的权限赋给用户 USER1。


参考答案:


(1)GRANT ALL PRIVILEGES ON TABLE S,P,J TO USER1,USER2;


(2)GRANT INSERT ON TABLE S TO USER1 WITH GRANT OPTION;

(3)GRANT CREATE TABLE ON DATABASE SPJ TO USER1;

6.2 销权(REVOKE)

销权语法格式:

REVOKE <权限>[,<权限>]...
[ON<对象类型><对象名>]
FROM <用户>[,<用户>]...
[RESTRICT|CASCADE];

其中:RESTRICT 表示只收回指定用户的权限,默认;CASCADE 表示收回指定用户及其授予的其他用户的该权限。


示例22. 要求回收用户对数据库SPJ中供应商S、零件P、 项目J表的操作权限。各种收回权限的要求如下:


(1) 将用户USER1 及USER2对供应商S、零件P、项目J的所有操作权限收回。


(2) 将所有用户对供应商S的所有查询权限收回 。


(3)将USER1 用户对供应商S的供应商编号Sno的修改权限收回。


参考答案:


(1) REVOKE AL PRIVILEGES ON TABLE S,P,J FROM USER1, USER2;


(2) REVOKE SELECT ON TABLE S FROM PUBLIC;


(3) REVOKE UPDATE(Sno) ON TABLE S FROM USER1;


示例23. 收回用户LI对表EMPLOYEE的查询权限,同时级联收回LI授予其他用户的该权限,SQL语句为: (1) SELECT ON TABLE EMPLOYEE FROM LI (2) ;


(1) A.GRANT    B.GIVE    C.CALL BACK    D. REVOKE


(2) A.RESTRICT    B.CASCADE    C.WITH GRANT OPTION    D. WITH CHECK OPTION


答案:(1)的正确选项为D,(2)的正确选项为B。

7. 存储过程和触发器

存储过程,类似于高阶语言的函数或者方法,包含SQL语句序列,是可复用的语句,保存在数据库中,在服务器中执行。


特点:复用,提高了效率,安全性。


触发器是一种特殊类型的存储过程,是通过事件触发而执行的,而存储过程可以通过存储过程名称而被直接调用。


触发器主要有如下特点:


(1) 当数据库程序员声明的事件发生时,触发器被激活。事件可以是对某个特定关系的插入(INSERT)、删除(DELETE)或更新(UPDATE)。


(2)当触发器被事件激活时,不是立即执行,而是首先由触发器测试触发条件,若条件不成立,响应该事件的触发器什么事情都不做。


(3)如果触发器声明的条件满足,则与该触发器相连的动作由DBMS执行。动作可以阻止事件发生,可以撤销事件。


触发器数据库对象,当创建一个触发器时必须指定:1> 名称;2> 在其上定义触发器的表;3> 触发器将何时激发;4> 指明触发器执行时应做的动作。其名称必须遵循标识符的命名规则,数据库像存储普通数据那样存储触发器。触发器可以引用当前数据库以外的对象,但只能在当前数据库中创建触发器。尽管不能在临时表或系统表上创建触发器,但是触发器可以引用临时表。


触发动作实际上是一系列SQL语句,可以有两种方式:


(1) 对被事件影响的每一行(FOR EACH ROW),每一元组执行触发过程,称为行级触发器。


(2) 对整个事件只执行一次触发过程(FOR EACH STATEMENT),称为语句级触发器。该方式是触发器的默认方式。

7.1 创建触发器

触发器主要包括两个方面:指明触发器的触发事件,指明触发器执行的动作。


触发事件包括表中行的插入、删除和修改,即执行 INSERT、DELETE、UPDATE 语句。 在修改操作 (UPDATE)中,还可以指定特定的属性或属性组的修改为触发条件。事件的触发还有两个相关的时间:BEFORE 和 AFTER。BEFORE 触发器是在事件发生之前触发,AFTER 触发器是在事件发生之后触发。创建触发器语句格式如下:

CREATE TRIGGER <触发器名> [{BEFORE|AFTER}]
{[DELETE|INSERT|UPDATE OF[列名清单]]}
ON 
[REFERENCING <临时视图名>]
[FOR EACH ROW|FOR EACH STATEMENT]
[WHEN <触发条件>]
BEGIN
<触发动作>
END [触发器名];

参数说明:


BEFORE:指示 DBMS 在执行触发语句之前激发触发器。

AFTER:指示 DBMS在执行触发语句之后激发触发器。

DELETE:指明是 DELETE 触发器,每当一个DELETE 语句从表中删除一行时激发触发器。

INSERT:指明是 INSERT 触发器,每当一个INSERT语句向表中插入一行时激发触发器

UPDATE:指明是 UPDATE 触发器,每当 UPDATE 语句修改由 OF 子句指定的列值时,激发触发器。如果忽略 OF 子句,每当 UDPATE 语句修改表的任何列值时,DBMS 都将激发触发器。

REFERENCING <临时视图名>:指定临时视图的别名 。在触发器运行过程中,系统会生成两个临时视图,分别存放被更新值(旧值)和更新后的值(新值)。对于行级触发器, 默认临时视图名分别是 OLD 和 NEW;对于语句级触发器,默认临时视图名分别是 OLD-TABLE 和 NEW-TABLE。一旦触发器运行结束,临时视图就不在。

WHEN <触发条件>:指定触发器的触发条件。当满足触发条件时,DBMS 才激发触发器。触发条件中必须包含临时视图名,不包含查询。

示例24. 银行数据库关系模式如下:

            Account (Account-no, branch-name, balance)

            Loan (Loan-no, branch-name, amount)

            Depositor (customer-name, Account-no)

账户关系模式 Account 中的属性 Account-no 表示账号 ,branch-name 表示支行名称,balance 表示余额。贷款关系模式 Loan 中的属性 Loan-no 表示贷款号,branch-name 表示支行名称,amount 表示金额。存款关系模式 Depositor 中的属性 customer-name 表示存款人姓名。SQL-99 创建触发器如下所示:

CREATE TRIGGER overdraft_trigger AFTER UPDATE ON Account
REFERENCING NEW ROW AS nrow
FOR EACH ROW 
WHEN nrow.balance < 0 
BEGIN ATOMIC
INSERT INTO borrower
(SELECT customer-name,Account-no
FROM Depositor
WHERE nrow.account-no = Depositor.account-no);
INSERT INTO loan VALUES (nrow.account-no,branch-name,-nrow.balance);
UPDATE account SET balance = 0
WHERE account.account-no = nrow.account-no;
END;
CREATE TRIGGER reorder_trigger AFTER UPDATE OF amount on inventory
REFERENCING OLD ROW AS orow,NEW ROW AS nrow
FOR EACH ROW 
WHEN nrow.level <= (SELECT level
                    FROM minlevel
                    WHERE minlevel.item = orow.item)
AND orow.level > (SELECT level
                  FROM minlevel
                  WHERE minlevel.item = orow.item)
BEGIN 
INSERT INTO orders
(SELECT item,amount
FROM reorder
WHERE reorder.item = orow.item)
END;

示例26. 若修改某商品的库存时,使得库存值小于或等于其最小库存值,则向采购表插入一条记录,要求采购的数量是该商品最小库存值的两倍再加上10。

CREATE TRIGGER 采购-trigger AFTER UPDATE ON 商品 [AFTER UPDATE OF 库存 ON 商品]
REFERENCING NEW ROW AS nrow
FOR EACH ROW
WHEN nrow.库存<=nrow.最小库存
BEGIN
INSERT INTO 采购(商品号,采购数量)
VALUES(nrow.商品号,nrow.最小库存*2+10)
END;

爆肝!一看就懂的《SQL 语言知识体系》【建议收藏】(下):https://developer.aliyun.com/article/1529607

相关文章
|
3月前
|
SQL 关系型数据库 MySQL
在MySQL中,什么是结构化查询语言 (SQL)
【8月更文挑战第20天】在MySQL中,什么是结构化查询语言 (SQL)
57 1
|
22天前
|
SQL Oracle 关系型数据库
SQL语言的主要标准及其应用技巧
SQL(Structured Query Language)是数据库领域的标准语言,广泛应用于各种数据库管理系统(DBMS)中,如MySQL、Oracle、SQL Server等
|
25天前
|
SQL 关系型数据库 MySQL
Go语言项目高效对接SQL数据库:实践技巧与方法
在Go语言项目中,与SQL数据库进行对接是一项基础且重要的任务
41 11
|
3月前
|
SQL 关系型数据库 MySQL
|
3月前
|
SQL 存储 大数据
SQL 语言发展史简直太震撼啦!从诞生到现代数据处理,见证一场奇妙的演变之旅,快来感受!
【8月更文挑战第31天】SQL(结构化查询语言)自20世纪70年代由IBM研究员E.F. Codd提出以来,已成为现代数据处理不可或缺的一部分。它最初简化了层次和网状模型中复杂的存储与检索问题,通过基本的SELECT、FROM和WHERE关键字实现了数据查询。80年代,SQL在商业数据库中广泛应用,引入了GROUP BY、HAVING和ORDER BY等功能,增强了数据分析能力。90年代,互联网和企业信息化推动了SQL的进一步优化与扩展,支持分布式数据库和数据仓库等技术。
45 0
|
3月前
|
SQL 存储 NoSQL
从SQL到NoSQL:理解不同数据库类型的选择与应用——深入比较数据模型、扩展性、查询语言、一致性和适用场景,为数据存储提供全面决策指南
【8月更文挑战第31天】在信息技术飞速发展的今天,数据库的选择至关重要。传统的SQL数据库因其稳定的事务性和强大的查询能力被广泛应用,而NoSQL数据库则凭借其灵活性和水平扩展性受到关注。本文对比了两种数据库类型的特点,帮助开发者根据应用场景做出合理选择。SQL数据库遵循关系模型,适合处理结构化数据和复杂查询;NoSQL数据库支持多种数据模型,适用于非结构化或半结构化数据。SQL数据库在一致性方面表现优异,但扩展性较差;NoSQL数据库则设计之初便考虑了水平扩展性。SQL使用成熟的SQL语言,NoSQL的查询语言更为灵活。
70 0
|
3月前
|
SQL 数据可视化 数据挖掘
SQL 在数据分析中简直太牛啦!从数据提取到可视化,带你领略强大数据库语言的神奇魅力!
【8月更文挑战第31天】在数据驱动时代,SQL(Structured Query Language)作为强大的数据库查询语言,在数据分析中扮演着关键角色。它不仅能够高效准确地提取所需数据,还能通过丰富的函数和操作符对数据进行清洗与转换,确保其适用于进一步分析。借助 SQL 的聚合、分组及排序功能,用户可以从多角度深入分析数据,为企业决策提供有力支持。尽管 SQL 本身不支持数据可视化,但其查询结果可轻松导出至 Excel、Python、R 等工具中进行可视化处理,帮助用户更直观地理解数据。掌握 SQL 可显著提升数据分析效率,助力挖掘数据价值。
59 0
|
3月前
|
SQL Java 数据库连接
|
3月前
|
SQL 数据库 索引
SQL语言入门:如何表达你的数据需求
在数据库的世界里,SQL(Structured Query Language)是一种至关重要的语言,它允许用户与数据库进行交互,执行数据的查询、更新、插入和删除等操作
|
3月前
|
SQL 关系型数据库 MySQL
Go语言中进行MySQL预处理和SQL注入防护
在现代Web应用开发中,安全性至关重要。SQL注入是一种常见的攻击方式,攻击者可通过构造特殊SQL查询来非法访问或修改数据库数据。本文介绍如何利用Go语言中的预处理SQL语句来防范此类攻击。预处理不仅能提升安全性,还能提高性能并简化代码。通过使用`?`作为占位符,Go自动处理参数转义,有效避免SQL注入。此外,文章还提供了连接MySQL数据库、执行预处理查询以及最佳实践的示例代码。务必遵循这些指导原则,确保应用程序的安全性。
88 0