SQL 是结构化查询语言,SQL-92 是目前最通用的版本,后续版本引入了更强的功能(如对象关系特性、XML 支持等)

1.Data Definition Language 数据定义语言(DDL)

数据库中的关系集合必须通过 DDL 定义。除了关系集合本身,还可以指定:

每个关系的模式(schema);每个属性的值域(domain);完整性约束(integrity constraints);每个关系维护的索引集合;安全性与访问控制;每个关系在磁盘上的物理存储结构

DDL 用来定义数据库结构,而不是查询或操作数据。

SQL 中的 CREATEALTERDROP 等命令都属于 DDL。

2.SQL中的域类型

char(n):固定长度字符;varchar(n):可变长度字符(最大长度 n);int:整数(取决于机器);smallint:小整数(范围更小);numeric(p,d):定点数,p 是总位数,d 是小数位数;real:单精度浮点数;float(n):浮点数,精度至少 n 位

这些数据类型在不同数据库中的表现可能有差异,例如 Oracle、MySQL、PostgreSQL 对浮点数精度的实现不同。

3.建表语句

SQL 用 CREATE TABLE 定义关系:

create table r (A1 D1,A2 D2, ..., An Dn,
               (integrity-constraint1),
                ...,
                (integrity-constraintk))

r 是关系名

Ai 是属性名

完整性约束可以写在列定义后或单独定义

eg:

create table people (
  name char(15) not null,
  city char(30),
  assets int
)

not null 表示该字段不能为空。

4.完整性约束

SQL 支持多种完整性约束,例如:

primary key (A1, …, An) 主键

not null 不允许空值

eg:

create table people (
  name char(15),
  city char(30),
  assets int,
  primary key (name))

主键约束会隐含 not null,不需要单独声明。

5.删除表:drop table r

6.增加新属性:alter table r add A D

新属性的值默认为 null

7.删除属性:alter table r drop A

很多数据库不支持删除列

MySQL、PostgreSQL 等现代数据库都支持 alter table drop column,但一些老系统(例如早期的 Oracle)不支持

8.基本查询结构

SQL 基于集合和关系代数操作,并做了增强。

典型 SQL 查询:

select A1, A2, …, An
from r1, r2, …, rm
where P

Ai:属性

ri:关系(表)

P:谓词(条件)

查询结果仍然是一个关系。

对应关系代数:选择 (σ)、投影 (π)、笛卡尔积 (×)。

9.select 子句:列出查询结果中所需的属性

select 对应关系代数中的投影 (π)。

SQL 名称大小写不敏感。Branch_Name ≡ BRANCH_NAME ≡ branch_name

SQL 允许查询结果中出现重复行。如果想去重,需要在 select 后加 distinct

select distinct branch_name
from loan

保留重复:

select all branch_name
from loan

关系代数与 SQL 区别:在形式化的关系代数中,结果是集合,天然去重。SQL 默认允许重复,优化性能

形式化关系模型:关系是集合,不能有重复元组。

实际数据库系统:去重代价高 → SQL 默认允许重复

可以用 distinct 强制去重。

SQL 更像是“多重集(multiset)模型”

ID name dept_name salary
100 Kart CS 65000
101 Crick History 90000
102 Kim Finance 60000
103 Wu Physics 72000
104 John CS 80000

查询:

select distinct dept_name
from Instructor;

提取所有不同的系名。

结果:

dept_name
CS
History
Finance
Physics

重复的“CS” 被去掉了。

查询:

select all dept_name
from Instructor

结果:

dept_name
CS
History
Finance
Physics
CS

使用 all → 重复行不会被去掉

select * 的用法:

* 表示所有属性。

表 loan:

loan_number branch_name amount
0001 Perryridge 1000
0002 Downtown 500
select *
from loan

结果: 与 loan 表内容相同。

select 中可以出现算术表达式:可使用 +, -, *, / 运算符。运算对象:常数或列属性。

eg:

select number, name, asset*100
from account;

→ 把 asset 字段放大 100 倍。

10.where 子句:指定查询结果必须满足的条件

where 用来写条件 → 对应关系代数中的选择 (σ)

比较结果可以用逻辑运算符组合:and, or, not。比较对象可以是算术表达式的结果。

支持范围:between a and b,区间是闭区间

不等于:<>

eg:

select asset
from account
where name = 'peter' and number > 1200

11.from 子句与连接:列出查询涉及的关系(表)

from 指定涉及的表,对应笛卡尔积.

eg:

select *
from borrower, loan

= borrower × loan

通常结合 where → 做“过滤”,得到连接。

eg:

SELECT ACC.acc_id, CUST.name
FROM CUST, ACC
WHERE CUST.cust_id = ACC.cust_id

→ 查询账户 id 与其所有者姓名。

当多个表中列名无歧义时,可以简化书写;可用别名(AS)。

select customer_name, borrower.loan_number as loan_id, amount
from borrower, loan
where borrower.loan_number = loan.loan_number
SELECT customer_id AS cid
FROM CUST

12.Rename 与元组变量

元组变量通过 FROM 子句的 AS 引入。

AS 可以给列或表重命名

表别名常用于:简化查询; 同一表多次引用(如自连接)。

select C.name, T.loan_number, S.amount
from borrower as T, loan as S
where T.loan_number = S.loan_number;

13.字符串操作

like 用于模式匹配:% 匹配任意长度字符串; _ 匹配任意一个字符

'Intro%' → 匹配以 Intro 开头的字符串

'%Comm%' → 匹配包含“Comm”的字符串(如 “Intro to COMM School”, “Communication”)

'___' → 匹配恰好三个字符的字符串

'___%' → 匹配至少三个字符的字符串

where name like '%lucy%'

→ 匹配含有“lucy”的名字。

可以指定 escape 转义特殊字符。

匹配所有以 “100%” 开头的字符串:

like '100\%%' escape '\'

转义符 escape 表示其后字符当作普通字符。

14.排序

order by 指定排序,默认升序 (asc)。

可写 desc 表示降序。

select distinct customer_name
from borrower, loan
where borrower.loan_number = loan.loan_number
  and branch_name = 'Perryridge'
order by customer_name;
order by customer_name desc

SQL 查询结果默认无序,除非显式 order by

15.重复

SQL 允许关系和查询结果中出现重复元组。

多重集 (multiset):允许重复元素的集合。

假设有多重集关系:

r1:

A B
1 a
2 a

r2:

C
2
3
3
SELECT B, C
FROM r1, r2

结果:

B C
a 2
a 3
a 3
a 2
a 3
a 3

因为 r2 中有重复的 “3”,结果里也会出现重复。

16.集合运算

SQL 的集合操作:unionintersectexcept

对应关系代数中的并集 (∪)、交集 (∩)、差集 (−)。

这些操作默认 自动去重

如果要保留重复,用多重集版本:

union all

intersect all

except all

SQL 既支持集合语义(去重),也支持多重集语义(允许重复)。

集合操作要求两个查询返回 相同数量和类型的列

(SELECT cust_id FROM CUST)
INTERSECT
(SELECT cust_id FROM ACC)
(SELECT cust_id
 FROM CUST)
UNION
(SELECT cust_id
 FROM ACC)
(SELECT cust_id
 FROM CUST)
EXCEPT
(SELECT cust_id
 FROM ACC)

返回 在 CUST 中但不在 ACC 中 的 id。

如果没有这样的 id,结果就是 空集

17.聚合函数

聚合函数:以一个集合的值作为输入,返回一个单一值

常见函数:

avg 平均值

min 最小值

max 最大值

sum 求和

count 计数

聚合函数 不能直接 用在 where 子句中

SELECT SUM(amount)
FROM DEPOSIT
WHERE acc_id = 'A1'
SELECT COUNT(*)
FROM DEPOSIT
WHERE acc_id = 'A1'
SELECT COUNT(DISTINCT cust_id)
FROM DEPOSIT
WHERE acc_id = 'A1'

DISTINCT 可以避免同一个顾客多次存款被重复计数。

group by 按组聚合

SELECT acc_id, SUM(amount)
FROM DEPOSIT
GROUP BY acc_id
SELECT acc_id, cust_id, SUM(amount)
FROM DEPOSIT
GROUP BY acc_id, cust_id

GROUP BY 查询中:SELECT 子句可以包含:

  • 分组属性(必须出现在 GROUP BY 中)

  • 聚合函数(参数可以是任何属性)

每一组只有一个聚合值。

18.Having 子句

HAVING 只能和 GROUP BY 一起使用,用于对组结果进一步过滤。

找出每个账户的总存款,要求该账户至少有两次存款:

select acc_id, sum(amount)
from deposit
group by acc_id
having count(*) >= 2

执行顺序:

WHERE 在分组前过滤元组。

GROUP BY 把剩余元组分组。

HAVING 在分组后过滤组。

HAVING 子句通常包含聚合函数。

WHERE 子句不能包含聚合函数.

特性 WHERE 子句 HAVING 子句
执行时机 在分组执行 在分组执行
操作对象 原始数据行(元组) 分组后的组
可使用 普通列、比较运算符 聚合函数、分组后的列
用途 过滤掉不需要的行 过滤掉不需要的组

19.Null 值

在 SQL 中,元组的某些属性可能取值为 null

null 表示:未知的值或者值不存在

检查空值:使用 is nullis not null

select loan_number
from loan
where amount is null

任意算术表达式中包含 null,结果也是 null

5 + null → null

任何与 null 的比较,结果都是 unknown

5 < null → unknown

null <> null → unknown

null = null → unknown

SQL 逻辑是 三值逻辑:true / false / unknown

逻辑运算规则:

OR:

(unknown OR true) = true

(unknown OR false) = unknown

(unknown OR unknown) = unknown

AND:

(true AND unknown) = unknown

(false AND unknown) = false

(unknown AND unknown) = unknown

NOT:

(NOT unknown) = unknown

OR 真值表

OR TRUE FALSE UNKNOWN
TRUE TRUE TRUE TRUE
FALSE TRUE FALSE UNKNOWN
UNKNOWN TRUE UNKNOWN UNKNOWN

AND 真值表

AND TRUE FALSE UNKNOWN
TRUE TRUE FALSE UNKNOWN
FALSE FALSE FALSE FALSE
UNKNOWN UNKNOWN FALSE UNKNOWN

NOT 真值表

输入 NOT 结果
TRUE FALSE
FALSE TRUE
UNKNOWN UNKNOWN

还可以用:is unknown/ is not unknown

where 子句中,unknown 被当作 false 处理

除了 count(*),所有聚合函数都会忽略属性值为 null 的元组。

select sum(amount)
from loan

在求和时,null 金额会被忽略。如果所有值都是 null → 结果为 null。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐