sql.js
内置类型 | 含义 |
---|---|
CHAR(n) or CHARACTER(n) | 定长度字符串 |
VARCHAR(n) or CHARACTER VARYING(n) | 变长度字符串(最大长度为 n ) |
INT or INTEGER | |
S | |
NUMERIC(p, d) | 定点数(p 位十进制小数,小数点后 d 位) |
REAL , DOUBLE PRECISION | 浮点数 |
FLOAT(n) | 浮点数(至少 n 位十进制小数) |
创建 relation:
其中 NOT NULL
规定该 attribute 不能取空值,integrity_constraint_i
可以是任意 integrity constraints,例如:
删除 relation:
增删 attributes:
查询单一 attribute:
查询多个 attributes 并做算术运算:
带条件(可用 AND
, OR
, NOT
相连)查询:
不同 relations 的同名 attributes 以 relation.attribute
的方式区分:
一般形式的查询由三个 clauses 构成:
逻辑上分三步:
FROM
-clause 中的 relation
s 的 Cartesian productWHERE
-clause 中的 predicate
筛选上述 Cartesian product 的 tuplesSELECT
-clause 中的 attribute
s of 上述 tuples(可以用 *
表示所有 attributes)AS
— 重命名重命名 attribute:
重命名 relations:
LIKE
— 字符串匹配字符串用单引号界定,字符串内的单引号用双引号代替。
模式匹配:
%
匹配任意子字符串_
匹配任意字符\
表示转义字符例如
ORDER BY
— 输出排序按某个 attribute 升序排列:
按多个 attributes 依次排列:
BETWEEN
— 数值范围UNION
INTERSECT
⚠️ MySQL 不支持 INTERSECT
。
EXCEPT
⚠️ MySQL 不支持 EXCEPT
;Oracle 用 MINUS
代替 EXCEPT
;Oracle-12c 用 MULTISET EXCEPT
代替 EXCEPT ALL
。
WHERE
-clause 中
NULL
的算术运算,结果为 NULL
;NULL
的比较运算,结果为 UNKNOWN
。SELECT
-clause 中的 DISTINCT
将两个 NULL
视为相同的值。
COALESCE
以任意多个相同类型为输入,返回第一个非空值:
DECODE
in Oracle不要求类型相同,按第一个匹配替换:
⚠️ 与一般情形不同,NULL
与 NULL
视为相等。
将 NULL
替换为 N/A
:
SQL 提供 5 个基本聚合函数,它们以集合为输入,以单值(的集合)为输出。
AVG
, SUM
的输入必须是数值的集合MIN
, MAX
, COUNT
的输入可以是其他类型数据的集合除 COUNT(*)
外,均忽略 NULL
;作用于空集时,COUNT
返回 0
,其余返回 NULL
。
GROUP BY
— 分组按 dept_name
分组,计算各组的 AVG(salary)
:
⚠️ 未出现在 GROUP BY
-clause 里的 attributes,在 SELECT
-clause 中只能作为聚合函数的输入,不能作为输出的 attributes。
HAVING
— 组条件平均工资大于 42000 的系:
逻辑顺序:
FROM
-clause 构造 Cartesian productWHERE
-clause 筛选 tuplesGROUP BY
-clause 分组(默认为一组)HAVING
-clause 对各 groups 进行筛选SELECT
-clause 指定的 attributes (of groups)IN
— 这里的“集合”可以是形如 (SELECT ...)
的子查询结果,或形如 (v_1, ..., v_n)
的枚举集。
与 INTERSECT
等价:
与 EXCEPT
等价:
SOME
— ⚠️ 与 ANY
为同义词,早期版本的 SQL 只支持 ANY
。
ALL
— EXISTS
— 集合非空其中 S
在外层查询定义,可以在内层子查询中使用。作用域规则与高级编程语言类似。
上过生物系所有课程的学生:
UNIQUE
— 无重复2017 年至多开过一次的课程:
等价于
⚠️ 若 NULL
,其余同名 attributes 的值均非空且相等,则 UNKNOWN
;而 UNIQUE
当且仅当存在 TRUE
时才返回 FALSE
;故在此情形下,UNIQUE
依然返回 TRUE
。
FROM
-clause 中的子查询与 HAVING
等价的写法:
子查询结果是一个 relation,可将其命名为 dept_avg
,它含有 dept_name
, avg_salary
这两个 attributes:
⚠️ MySQL 及 PostgreSQL 规定 FROM
-clause 中的子查询结果必须被命名。
自 SQL-2003 起,支持用 LATERAL
访问 FROM
-clause 中已出现过的 relation:
WITH
— Temporary Relations拥有最大预算的系:
通常比嵌套的子查询更清晰,且临时关系可在多处复用。
可以创建多个临时关系:
返回单值(之集)的子查询,可用在 SELECT
-, WHERE
-, HAVING
-clauses 中接收单值的地方。
查询各系及其讲师人数:
若含有 WHERE
-clause,则先完成该 clause,再修改 relation。
DELETE FROM
与 SELECT
类似:
每次只能从一个 relation 中删除 tuples。
WHERE
-clause 可以含子查询:
INSERT INTO
按 attributes 在 schema 中的顺序插入 values:
或显式给定顺序(可以与 schema 中的不一致):
更一般的,可以插入查询结果:
UPDATE ... SET
所有讲师涨薪 5%:
收入小于平均收入的讲师涨薪 5%:
条件分支:
标量子查询可用于 SET
-clause:
CROSS JOIN
表示 Cartesian product,可以用 ,
代替:
NATURAL JOIN
只保留 Cartesian product 中同名 attributes 取相同值的 tuples,且同名 attributes 只保留一个。
可以用 JOIN r USING (a)
指定与 r
连接时需相等的 attribute(s):
ON
— Conditional JoinINNER JOIN
以上 JOIN
s 都是 INNER JOIN
,其中 INNER
可以省略。
OUTER JOIN
OUTER JOIN
为没有参与 INNER JOIN
的单侧 tuple 提供 NULL
值配对,即:允许来自一侧 tuple 在另一侧中缺少与之匹配的 tuple。在连接后的 tuple 中,缺失的值置为 NULL
。
在连接结果中保留没有选课的学生,其选课信息置为 NULL
:
OUTER JOIN
也可以配合 ON
使用:
with
-clause 可在单个 query 内创建临时关系。
CREATE VIEW
各系系名及该系讲师的总工资:
为避免数据过期,view 通常在被使用时才会去执行 query。
为节省时间,某些数据库系统支持 materialized view,以负责预存并(在 query 中的 relation(s) 被更新时)更新 view 中的数据。存在多种更新策略:
满足以下条件的 view 可以被更新:
FROM
-clause 只含 1 个实际 relationSELECT
-clause 只含 attribute names,不含表达式、聚合函数、DISTINCT
修饰NULL
值GROUP BY
或 HAVING
💡 推荐用 trigger 机制更新 view。
每个 transaction 由一组不可分的 statements 构成,整体效果为 all-or-nothing,只能以以下两种方式之一结束:
MySQL、PostgreSQL 默认将每一条 statement 视为一个 transaction,且执行完后自动提交。
为创建含多条 statements 的 transaction,必须关闭自动提交机制。
BEGIN ATOMIC ... END
中,以创建 transaction。BEGIN
但不支持 END
,必须以 COMMIT
或 ROLLBACK
结尾。从 Alice’s 账户向 Bob’s 账户转账 100 元,所涉及的两步 UPDATE
操作是不可分的:
PostgreSQL 支持更精细的提交/回滚控制:
可以在 CREATE TABLE
时给定,也可以向已有的 relation 中添加:
NOT NULL
— 非空值默认 NULL
属于所有 domains;若要从某个 domain 中排除 NULL
,可在 domain 后加 NOT NULL
:
PRIMARY KEY
默认为 NOT NULL
。
UNIQUE
— Superkey⚠️ NULL
不等于任何值,参见 NULL = NULL
。
CHECK
— 条件检查⚠️ 除 CHECK(TRUE)
外,CHECK(UNKNOWN)
亦返回 TRUE
。
⚠️ SQL 标准支持 CHECK
中含 subquery,但多数系统尚未支持。
REFERENCES
— 外键约束亦可在 attribute 定义中使用:
违反约束的操作默认被拒绝(transaction 回滚),但 FOREIGN KEY
允许设置 CASCADE
等操作:
除 CASCADE
外,还支持 SET NULL
或 SET DEFAULT
操作。
⚠️ 含有 NULL
的 tuple 默认满足约束。
💡 借助 triggers 可实现更一般的 referential integrity constraints。
CONSTRAINT
— 约束命名某些场景必须临时违反约束,例如:
SQL 标准支持
INITIALLY DEFERRED
修饰约束,表示该约束延迟到 transaction 末尾才检查。DEFERRABLE
修饰约束,表示该约束默认立即检查,但可以在 transaction 中用延迟到末尾。
ASSERTION
tot_cred
= 其已通过课程的学分之和:
💡 SQL 不支持
⚠️ 因开销巨大,多数系统尚未支持 ASSERTION
。
抽取信息:
获取当前时间:
CAST(e AS t)
将表达式 e
转化为类型t
:
MySQL:
DEFAULT
— 默认值*LOB
— Large OBjectCLOB
— Character LOBBLOB
— Binary LOB可以定义 LOB attributes:
⚠️ LOB 的读写效率很低,一般以其 locator 作为 attribute,而非对象本身。
CREATE TYPE
美元与英镑不应当能直接比较、算术运算,可通过定义类型加以区分:
CREATE DOMAIN
SQL-92 支持自定义 domain,以施加完整性约束、默认值:
⚠️ 不同自定义 domain 的值直接可以直接比较、算术运算。
若 always
替换为 BY DEFAULT
,则允许用户给定 ID 值。
相当于
由查询结果推断 schema:
CREATE SCHEMA
数据库系统 | 操作系统 |
---|---|
catalog | home directory of a user |
schema | a directory in ~ |
relations, views | files |
connect to a DBS | log into a OS |
default catalog & schema | ~ |
catalog5.univ_schema.course | /home/username/filename |
等价于
Index 将一组 attributes 组合为一个 search key,用来避免遍历所有 tuples 从而加速查找。
Index 与物理层相关,而 SQL 标准限于逻辑层,故没有提供 index 定义命令;但很多数据库系统提供了以下命令:
最高权限属于数据库管理员 (DataBase Administrator, DBA),其权限包括授权、重构数据库等。
其中
privilege_list
可以包括
SELECT
,相当于文件系统中的 read 权限。INSERT
,可以在其后附加 (attribute_list)
,表示 INSERT
时只允许提供这些 attributes 的值。UPDATE
,可以在其后附加 (attribute_list)
,表示 UPDATE
时只允许修改这些 attributes 的值。REFERENCES
,可以在其后附加 (attribute_list)
,表示这些 attributes 可以被用作 FOREIGN KEY
或出现在 CHECK
约束中。DELETE
ALL PRIVILEGES
(创建 relation
的 user
自动获得 ALL PRIVILEGES
)。user_list
可以包括
PUBLIC
,表示当前及将来所有用户同类用户应当拥有相同权限。
Role 可以被赋予某个具体的 user 或其他 role:
默认当前 session 的 role 为 NULL
,但可显式指定:
此后赋权时可附加 GRANTED BY CURRENT_ROLE
,以避免 cascading revocation。
默认不允许转移权限,但可以用 WITH GRANT OPTION
赋予某个 user/role 传递权限的权限:
某个权限的权限传递关系构成一个 directed graph:以 users/roles 为 nodes(其中 DBA 为 root)、以权限传递关系为 edges,每个 user/role 有一条或多条来自 root 的路径。
撤回某个 user/role 的权限可能导致其下游 users/roles 的权限亦被撤销:
Java DataBase Connectivity (JDBC)
若要在 Java 程序中推断某个 relation 的 schema,可以从 ResultSet
对象中提取元数据:
💡 推荐用 prepareStatement
方法(由 SQL 系统完成代入并处理转义),以替代更危险的 String
串联操作:
类似地,可参数化 SQL 函数、过程调用:
psycopg2
is the most popular PostgreSQL database adapter for the Python programming language. pyodbc
is an open source Python module that makes accessing ODBC databases simple.Open Database Connectivity (ODBC)
Transactions 相关:
⚠️ 实际数据库系统给出的具体实现不同于 SQL 标准(本节)。
循环(LEAVE
相当于 break
,ITERATE
相当于 continue
):
条件分支:
输出某系讲师人数:
输出某系讲师信息:
⚠️ 可以同名:
PROCEDURE
s 的 arguments 个数必须不同。FUNCTION
s 的 arguments 个数可以相同,但至少有一个 argument 的类型不同。用例:规定某商品库存的最小值,当售出该商品导致库存量小于最小值时,自动下单订购该商品。
定义 trigger 需指定:
UPDATE
触发的 trigger 可以指定 attributes:
涉及的所有称为 transition tables:
⚠️ 只能用于 AFTER
triggres。
DISABLE
and ENABLE
Triggers 在创建时默认为启用的。可手动停用或启用:
用例:找到某一课程的所有(直接或间接)先修课程。
创建递归的临时表:
若以 CREATE RECURSIVE VIEW
代替 WITH RECURSIVE
,则创建递归的 view。
某些数据库系统允许省略 RECURSIVE
。
Recursive query 必须是单调的,即
NOT EXISTS
作用在用到 recursive view 的 subquery 上EXCEPT
右端项含有 recursive view假设 studentgr_grades
有每个学生的 ID
及其 GPA
,按 GPA
降序排序并输出排名:
默认将 NULL
视为最大值,可手动设为最小值:
假设有 dept_grades(ID, dept_name, GPA)
,则可先按 dept_name
分组,再对各组按 GPA
排名:
其他排名函数:
PERCENT_RANK
定义为分数 RANK
结果。CUME_DIST
定义为 ROW_NUMBER
相当于先对各 rows 排序,在输出各 row 的序号。NTILE(n)
将 tuples 按顺序均匀(各桶 tuples 数量至多相差 1
)分入 n
个桶,返回每个 tuple 的桶号。假设 tot_credits(year, num_credits)
含有每年的总学分。
对 (year-3, year]
的值取平均:
对 (year-3, year+2)
的值取平均:
对每年及之前所有年份的值取平均:
Windowing 也支持按 PARTITION
执行:
R
导出的 table T
,其中 R
的某个 attribute A
的值被 T
用作 attribute names,相应的值通常取某些聚合函数的返回值。A
。假设有 sales(name, size, color, quantity)
,以下语句得到以 (name, size, dark, pastel, white)
为 attributes 的 pivot-table:
GROUP BY ROLLUP(attribute_list)
表示以 attribute_list
的每个 prefix 作为 GROUP BY
的 attributes 列表,再对所有结果取 UNION
:
GROUP BY CUBE(attribute_list)
表示以 attribute_list
的每个 subset 作为 GROUP BY
的 attributes 列表,再对所有结果取 UNION
:
GROUPING
函数可判断 NULL
值是否由 ROLLUP
或 CUBE
产生: