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

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

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

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

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

SQL 中的 CREATE、ALTER、DROP 等命令都属于 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)模型”

IDnamedept_namesalary
100KartCS65000
101CrickHistory90000
102KimFinance60000
103WuPhysics72000
104JohnCS80000

查询:

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_numberbranch_nameamount
0001Perryridge1000
0002Downtown500
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:

AB
1a
2a

r2:

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

结果:

BC
a2
a3
a3
a2
a3
a3

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

16.集合运算

SQL 的集合操作:union、intersect、except

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

这些操作默认 自动去重。

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

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 null 或 is 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 真值表

ORTRUEFALSEUNKNOWN
TRUETRUETRUETRUE
FALSETRUEFALSEUNKNOWN
UNKNOWNTRUEUNKNOWNUNKNOWN

AND 真值表

ANDTRUEFALSEUNKNOWN
TRUETRUEFALSEUNKNOWN
FALSEFALSEFALSEFALSE
UNKNOWNUNKNOWNFALSEUNKNOWN

NOT 真值表

输入NOT 结果
TRUEFALSE
FALSETRUE
UNKNOWNUNKNOWN

还可以用:is unknown/ is not unknown

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

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

select sum(amount)
from loan

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

Logo

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

更多推荐