04 Intermediate SQL
Join Expressions
| join types | join conditions | 
| join (inner join) | NATURAL | 
| left outer | ON <predicate> | 
| right outer | USING(A1, A2,...) | 
| full outer |  | 
| 定义了不匹配键的处理方式 | 定义了用于匹配的键 | 
Join Conditions
Natural
相同的属性,只留下一个
|  | SELECT name, course_id
FROM student, takes
WHERE student.ID = takes.ID;
SELECT name, course_id
FROM student NATURAL JOIN takes;
 | 

如上图,只保留了一列 ID 属性
Warning
使用 {sql}NATURAL JOIN 的话,会自动将命名相同的属性匹配,但是可能这些属性的含义并不一样
e.g. 学生的学院和学生上课的开课学院
 
| 使用 using 来声明连接属性 | 
|---|
|  | SELECT name, title
FROM (student NATURAL JOIN takes) join course USING (coutse_id);
 | 
Others
- ON会保留多个属性
- USING(A1, A2,...)会将声明的同名属性合并
Join Types
- JOIN默认使用- INNER JOIN,不会保留有- NULL的 tuple
Outer Join
Note
如果 A 中的一个元素无法在 B 中找到匹配,也保留并补充空值
e.g. 一个没有修任何课程的学生,也希望在 {sql}student JOIN takes 中
 
- left outer join: 保留左边的全部信息
- right outer join: 保留右边
- full outer join: 保留两边
Views
- 用于向部分用户仅展示部分信息 hide certain data from the view of certain users
- Any relation that is not of the conceptual model but is made visible to a user as a virtual relation is called a view
Definition
|  | CREATE VIEW v AS
< query exp >;
 | 
- view definition 和使用 query 创建新的 relation 不同
- view definition 导致了 the saving of an expression,存储了查询表达式
 
| example | 
|---|
|  | CREATE VIEW faculty AS
    SELECT ID, name, dept_name
    FROM instructor;
CREATE VIEW dept_total_salary(dept_name, total_salary) AS
    SELECT dept_name, SUM(salary)
    FROM instructor
    GROUP BY dept_name;
 | 
by using other views
- 一个视图的定义可能依靠其他视图
- v1 is said to depend directly on v2,如果 v2 出现在了 v1 的定义中
- v1 is said to depend on v2,如果直接依赖、或者存在到 v2 的依赖路径
- v 可以是 recursive 的,如果依赖自己定义
| example | 
|---|
|  | CREATE VIEW physics_fall_2017 AS
    SELECT course, course_id, sec_id, building, room_number
    FROM course, section
    WHERE course.course_id = section.course_id
        AND course.dept_name = 'Physics'
        AND section.semester = 'Fall'
        AND section.year = '2017';
CREATE VIEW physics_fall_2017_watson ON
    SELECT course_id, room_number
    FROM physics_fall_2017
    WHERE building = 'Waston';
 | 
Expansion
|  | CREATE VIEW physics_fall_2017_watson ON
    SELECT course_id, room_number
    FROM physics_fall_2017
    WHERE building = 'Waston';
# expand to:
CREATE VIEW physics_fall_2017_watson ON
    SELECT course_id, room_number
    FROM (
        SELECT course, course_id, sec_id, building, room_number
        FROM course, section
        WHERE course.course_id = section.course_id
            AND course.dept_name = 'Physics'
            AND section.semester = 'Fall'
            AND section.year = '2017'
    )
    WHERE building = 'Waston';
 | 
Materialized Views
- 一些 DBMS 允许 view 能被物理存储
- 如果 relation 中的数据有更新,materialized view 需要维护
Update of a View
- 多数 SQL 都只支持简单视图的更新
- FROM只有一张表
- SELECT只有字段名,没有表达式,aggregates 或者- DISTINCT
- 所有没有放在 SELECT中的字段名允许NULL
- 没有 GROUP BY或者HAVING语句
 
examples
| example | 
|---|
|  | INSERT INTO faculty VALUES ('30756', 'Green', 'Music');
 | 
faculty 是 instructor 的视图,没有插入 salary 字段,有两种解决方法
| some updates cannot be translated uniquely | 
|---|
|  | CREATE VIEW instructor_info AS
    SELECT ID, name, building
    FROM instructor, department
    WHERE instructor.dept_name = department.dept_name;
INSERT INTO instructor_info VALUES ('67890', 'White', 'Taylor');
 | 
- 如果 Taylor有多个 department,是哪个?
- 如果 Taylor没有 department 怎么办?
| simple view outlier | 
|---|
|  | CREATE VIEW history_instructors AS
    SELECT *
    FROM instructor
    WHERE dept_name = 'History';
INSERT INTO history_instructors VALUES ('124554', 'Brown', 'Biology', 100000);  # 无法插入
 | 
Index
- 一张表上的 index 是一种数据结构,使得数据库系统能够快速查找一些类型的 tuple
```sql tilte="create index command"
CREATE INDEX  ON  (attr);
CREATE INDEX stuID_index on student(ID);
SELECT *
FROM student
WHERE ID = '12345';  # 能直接使用已有的 index 来查询
|  | # Transactions
- A **transaction** consists of a sequence of query and/or update statements and is a "unit" of work.
- transaction 一定以下面一种声明结束
    - **Commit work**: 提交 transaction 中的所有操作(永久化)
    - **Rollback work**: undone transaction 中的所有操作
- Atomic transaction: 只能完全执行或者 rollback
# Integrity Constraints
- `{sql}NOT NULL` 不允许字段为空
- `{sql}UNIQUE (A1, A2, ..., An)` 声明 `(A1, A2, ..., An)` 是一个 **super key**
    - 和主键不同,candidate keys 允许为 null
- `{sql}CHECK (P)`
    - `{sql}CHECK (semester in ('Fall', 'Winter', 'Spring', 'Summer')`
    - check 的条件可以非常复杂,可以嵌套 query
## Referential Integrity
- 保证一张表中出现的一些值能够对应到其他一些表上的一些值(foreign key)
    - `{sql}FOREIGN KEY (dept_name) REFERENCES department` 默认 ref 对应表的 primary key
    - `{sql}FOREIGN KEY (dept_name) REFERENCES department (dept_name)` 也可以自定义
```sql
CREATE TABLE person (
    ID CHAR(10),
    name CHAR(40),
    mother CHAR(10),
    father CHAR(10),
    PRIMARY KEY ID,
    FOREIGN KEY father REFERENCES person,
    FOREIGN KEY mother REFERENCES person
)
 | 
那么在插入的时候,要么先将 father, mother 设置为 null,要么取消 FOREIGN KEY 约束
Cascading Actions
| example | 
|---|
|  | CREATE TABLE course (
    ...,
    dept_name VARCHAR(20),
    FOREIGN KEY (dept_name) REFERNECES department
        ON DELETE CASCADE
        ON UPDATE CASCADE
    ...
)
 | 
也可以用 {sql}ON DELETE SET NULL / ON UPDATE SET DEFAULT
Assertions
- 表述 db 需要 always to satisfy 的条件
- {sql}CREATE ASSERTION <assertion-name> CHECK (<predicate>);
Triggers
- 系统根据数据库的修改自动执行的语句
- ECA rule
- E: event
- C: condition
- A: action
 
- introduced in SQL 1999
| example | 
|---|
|  | CREATE TRIGGER setnull_trigger BEFORE UPDATE OF takes ON grade
REFERENCING NEW ROW AS nrow
FOR EACH ROW
    WHEN (nrow.grade = '')
    BEGIN ATOMIC
        SET nrow.grade = NULL;
end;
 | 
- event: BEFORE/AFTER INSERT/DELETE/UPDATE OF <relation>
- REFERENCING OLD/NEW ROW AS
| trigger to maintain credits_earned value | 
|---|
|  | CREATE TRIGGER credits_earned AFTER UPDATE OF takes ON (grade)
REFERENCING NEW ROW AS nrow
REFERENCING OLD ROW AS orow
FOR EACH ROW
WHEN nrow.grade <> 'F' AND nrow.grade IS NOT NULL
    AND (orow.grade = 'F' OR orow.grade IS NULL)
BEGIN ATOMIC
    UPDATE student
    SET tot_cred = tot_cred + (
        SELECT credits
        FROM course
        WHERE course.course_id = nrow.course_id
    )
    WHERE student.id = nrow.id;
END;
 | 
when not to use
- 现在有更好的方法(materialized view)
- 可以封装方法,在更新的时候同时执行,而不是使用触发器
- risk of unintended execution
- 从 backup 中加载数据
- 将更新传递到远程数据库
- tip: 执行这些操作时可以 disable 触发器
 
Data Types
Built-in Data Types in SQL
- date: DATE '2005-7-27'
- time: TIME '09:00:30',TIME '09:00:30.75'
- timestamp: TIMESTAMP '2005-7-27 09:00:30.75'
- interval: INTERVAL '1' DAY
Large-Object Types
- BLOB: binary large object
- CLOB: character alrge object
| example | 
|---|
|  | book_review CLOB(10kB),
image BLOB(10MB),
movie BLOB(2GB)
 | 
- query 返回的不是大文件本身,而是一个 pointer(定位器)
User-Defined Types
| example | 
|---|
|  | CREATE TYPE Dollars AS NUMBERIC (12, 2) FINAL;
CREATE TABLE department (
    dept_name VARCHAR(20),
    building VARCHAR(15),
    budget Dollars
);
 | 
Domains
- 和 types 相似,但是可以有 constraints
|  | CREATE DOMAIN person_name CHAR(20) NOT NULL;
CREATE DOMAIN degree_level VARCHAR(10)
    CONSTRAINT degree_level_test
        CHECK (VALUE IN ('Bachelors', 'Masters', 'Doctorate'));
 | 
Authorization
Grant
|  | GRANT <privilege_list> ON <relation or view> TO <user_list>
 | 
- <user_list>- 
- a user-id
- PUBLIC所有合法用户
- a role (more on this later)
 
- 给视图权限不意味着给依赖的 relation 的权限
- 给权限的人 (grantor) 一定有这个权限
Privileges
- select
- insert
- update
- delete
- all privileges
Revoke
|  | REVOKE <privilege_list> ON <relation or view> FORM <user_list>
 | 
Roles
|  | CREATE ROLE <name>
GRANT <role> TO <users>
CREATE ROLE dean;
GRANT instructor TO dean;
GRANT dean TO Satoshi;
 | 
Authorization on Views
|  | CREATE VIEW geo_instructor AS
(
    SELECT *
    FROM instructor
    WHERE dept_name = 'Geology'
);
GRANT SELECT ON geo_instructor TO geo_staff;
 | 
- view creator 需要有 instructor的SELECT权限才能创建 view
- geo_staff 可以没有 instructor的任何权限?
Other Features
References 权限
- 有了才能去另一个 relation 引用 Foreign key
- {sql}GRANT REFERENCE (dept_name) ON department TO Mariano;
Transfer of privileges
| example | 
|---|
|  | GRANT SELECT ON department TO Amit WITH GRANT OPTION;
REVOKE SELECT ON department FROM Amit, Satoshi CASCADE;
REVOKE SELECT ON department FROM Amit, Satoshi RESTRICT;
 |