• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Oracle11g database sql语言基础
 

Oracle11g database sql语言基础

on

  • 1,254 views

 

Statistics

Views

Total Views
1,254
Views on SlideShare
1,254
Embed Views
0

Actions

Likes
1
Downloads
38
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Oracle11g database sql语言基础 Oracle11g database sql语言基础 Presentation Transcript

    • Oracle11g Database SQL 语言基础 2011.8 By Kevinlin. 林少杰 [email_address]
    • SQL 语言简介
      • SQL 语言 (Structured Query Language) 是访问关系型数据库的标准语言。
      • SQL 语言可以分为五种类型:
        • 查询 (QUERY) - SELECT
        • 数据处理 (DML)- INSERT, UPDATE, DELETE
        • 数据定义 (DDL) - CREATE, ALTER, DROP, RENAME, TRUNCATE
        • 事务控制 (TC) - COMMIT, ROLLBACK, SAVEPOINT
        • 数据控制 (DCL) – GRANT, REVOKE
      • SQL 语句可以被嵌入其他语句编写的程序里进行运行,比如 C++ 程序,也可以使用 JDBC 将 SQL 语句 写到 Java 程序里。
      • SQL 语句也可以使用一些工具运行,与数据库交互,比如 Oracle SQL*Plus , Oracle SQL Developer 以及其他第三方工具。
    • 查询数据
    • 使用 SELECT 查询数据 表 1 表 2 查询表中的若干行数据 查询表中的若干列 联合不同表 中的数据
    • 基本 SELECT 语句
        • SELECT 子句指定要查询的数据列。
        • FROM 子句指定对象表。
      SELECT *|{[DISTINCT] column | expression [ alias ],...} FROM table;
    • 查询所有列 SELECT * FROM departments;
    • 查询指定列 SELECT department_id, location_id FROM departments;
    • SELECT 语句编写
        • 大小写不敏感。
        • 可以写成一行或多行。
        • 关键字不能缩写或跨行。
        • 语句中的子句 (clause) 通常分行输入。
        • 缩进增加可读性。
        • 在一般的工具中, SQL 语句一般以分号“ ;” 结尾。
    • SELECT 语句中的四则运算 SELECT last_name, salary, 12*(salary+100) FROM employees;
    • Null 值
        • Null 值表示相应的值未知、不可用、未被分配。
        • Null 值不同于数字 0 或空格。
        • 所有与 Null 值相关的四则运行,结果为 Null 。
    • 定义列别名 ( Column Alias)
        • 重命名列名
        • 在有四则运算的情况下,可以使列名更具有意义
        • 列别名在定义时,紧跟列名,以空格或“ as” 分隔
        • 当列别名的大小写敏感,或者含有空格、特殊字符,需要使用双引号。
      SELECT last_name "Name" , salary*12 "Annual Salary" FROM employees; …
    • 连接符操作
        • 将列、字符串连接在一起,作为一个新列。
        • 连接符为两个竖线:“ ||”
        • 最终形成的列为字符表达式。
      SELECT last_name||job_id AS "Employees" FROM employees;
    • 原义字符串 ( Literal Character Strings)
        • 原义字符指字符、数字,或者日期。
        • 日期和字符需要使用单引号封装。
        • 每行数据显示一次。
      … SELECT last_name ||' is a '||job_id AS "Employee Details" FROM employees;
    • Quote ( q ) 操作
        • 可以选择分隔符。
        • 可选择任意方便的分隔符,单字节或多字节,或者下列符号 : [ ], { }, ( ), < > 。
        • 增加可读性与实用性。
      SELECT department_name || ' Department' || q'[ 's Manager Id: ]' || manager_id AS &quot;Department and Manager&quot; FROM departments;
    • 消除重复行 SELECT DISTINCT department_id FROM employees; … SELECT DISTINCT department_id , job_id FROM employees;
        • 可以在多个列之前使用 DISTINCT 修饰词,影响指定的所有列,其结果是这些列组合后的不同值。
    • DESCRIBE 命令 DESCRIBE employees
    • 限制返回结果
        • 使用 WHERE 子句限制返回结果 :
        • WHERE 子句在 FROM 子句之后。
      SELECT *|{[DISTINCT] column|expression [ alias ],...} FROM table [WHERE condition(s) ]; SELECT employee_id, last_name, job_id, department_id FROM employees WHERE department_id = 90 ;
    • 比较运算符 ( Comparison Operators) 不等于
        • <>
      两个值之间 ( 包括限值 ) BETWEEN ...AND... 符合列表内的值 IN(set) 符合字符样式 LIKE 是 null 值 IS NULL 小于
        • <
      小于或等于
        • <=
      大于或等于 >= 大于
        • >
      等于
        • =
      意义 运算符
    • 使用比较运算符 SELECT last_name, salary FROM employees WHERE salary <= 3000 ;
    • 使用比较运算符 SELECT last_name, salary FROM employees WHERE salary BETWEEN 2500 AND 3500 ;
        • 使用 BETWEEN 操作显示符合范围的值 :
      下限 上限
    • 使用比较运算符 SELECT employee_id, last_name, salary, manager_id FROM employees WHERE manager_id IN (100, 101, 201) ;
        • 使用 IN 操作符 显示符合列表内值的数据 :
    • 使用比较运算符
        • LIKE 操作符筛先符合查找字符串的数据行。
        • 查找条件可以包括字符或数字:
          • “ %” 表示数字 0 或者多个字符。
          • “ _” 表示一个字符。
      SELECT first_name FROM employees WHERE first_name LIKE 'S%' ;
    • 使用比较运算符
        • 可以同时使用 (%, _) 匹配符 :
        • 使用 ESCAPE “” 标识符查找值中含有“ %” 和 “ _” 字符的数据。
      SELECT last_name FROM employees WHERE last_name LIKE '_o%' ; SELECT last_name FROM employees WHERE last_name LIKE '%SA_%' ESCAPE '';
    • 使用比较运算符 SELECT last_name, manager_id FROM employees WHERE manager_id IS NULL ;
      • 使用 IS NULL 操作检验是否有 Null 值
    • 逻辑运算符 如果条件为假,则返回 TRUE NOT 如果前后两个条件有一个为真,则返回 TRUE
        • OR
      如果前后两个条件都为真,则返回 TRUE
        • AND
      Meaning Operator
    • 使用逻辑运算符 SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary >= 10000 AND job_id LIKE '%MAN%' ;
      • AND 需要前后两个条件为 TRUE:
    • 使用逻辑运算符
      • OR 需要前后两个条件有一个为 TRUE:
      SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary >= 10000 OR job_id LIKE '%MAN%' ;
    • 使用逻辑运算符
      • NOT 操作符可以与 IN, BETWEEN, LIKE, and NULL 配合使用 :
              • ... WHERE job_id NOT IN ('AC_ACCOUNT', 'AD_VP')
              • ... WHERE salary NOT BETWEEN 10000 AND 15000
              • ... WHERE last_name NOT LIKE '%A%‘
              • ... WHERE commission_pct IS NOT NULL
    • 运算符的优先级规则 可以使用括号改变默认的优先级别 Not equal to
        • 6
      NOT
        • 7
      AND
        • 8
      OR
        • 9
      IS [NOT] NULL , LIKE , [NOT] IN
        • 4
      [NOT] BETWEEN
        • 5
      比较运算符
        • 3
      连接运算符
        • 2
      四则运算
        • 1
      运算符 优先级
    • 排序 ORDER BY
        • 排序使用 ORDER BY 子句 :
            • ASC: 升序 ( 默认行为 )
            • DESC: 倒序
        • 如果不使用 ORDER BY ,相同的两次查询返回的结果顺序可以不一样。
        • 使用 NULL FIRST 和 NULL LAST 指定 NULL 值在排序中的位置。
        • ORDER BY 子句中的每个列都可以单独指定排序顺序。
    • 排序 ORDER BY
        • 默认的排序为升序:
          • 数字是最小的值在前 (1 to 999).
          • 日期的值最早的在前 (01-JAN-11 在 01-JAN-12 之前 )
          • 字符按字母表顺序 (“A” 最前,“ Z” 最后 ).
          • Null 值在升序时显示在最后面,在降序时显示在最前面
          • 可以使用一个不在 SELECT 列表中的列来排序
    • 替换变量 Substitution Variables
        • 替换变量临时保存数据,使用“ &” 和“ &&” 符号
        • 替换变量可用于:
          • WHERE 条件子句
          • ORDER BY 子句
          • 列表达式
          • 表名
          • 整个 SELECT 语句
      SELECT employee_id, last_name, job_id, &&column_name FROM employees ORDER BY &column_name ;
    • SQL 函数 SQL functions 函数 输入 参数 1 参数 2 参数 n 函数进行运算 输出 结果
    • SQL 函数的两种类型 单行函数 多行函数 每行返回一个结果 多行返回一个结果 函数
    • 单行函数 Single-Row Functions
      • 用于处理数据对象
      • 接收参数,然后输出一个结果
      • 每返回一行数据就要进行运算
      • 每行返回一个结果
      • 可以修改数据类型
      • 可以被嵌套
      • 参数可以是一个列或一个表达式
      function_name [( arg1, arg2,... )] 转换函数 字符函数 数字函数 日期函数 一般函数
    • 字符函数 Character Functions 字符函数 LOWER UPPER INITCAP CONCAT SUBSTR LENGTH INSTR LPAD | RPAD TRIM REPLACE 大小写转换函数 字符处理函数
    • 大小写转换函数 Case-Conversion sql course LOWER('SQL Course') Sql Course INITCAP('SQL Course') SQL COURSE UPPER('SQL Course') 结果 函数
    • 字符处理函数 BLACK and BLUE REPLACE ('JACK and JUE','J','BL') 10 LENGTH('HelloWorld') 6 INSTR('HelloWorld', 'W') *****24000 LPAD(salary,10,'*') 24000***** RPAD(salary, 10, '*') HelloWorld CONCAT('Hello', 'World') elloWorld TRIM('H' FROM 'HelloWorld') Hello SUBSTR('HelloWorld',1,5) 结果 函数
    • 数字函数 100 MOD(1600, 300) 45.93 ROUND(45.926, 2) 45.92 TRUNC(45.926, 2) 结果 函数
    • 日期函数 '08-SEP-95' NEXT_DAY ('01-SEP-95','FRIDAY') '28-FEB-95' LAST_DAY ('01-FEB-95') 19.6774194 MONTHS_BETWEEN ('01-SEP-95','11-JAN-94') ‘ 29-FEB-96' ADD_MONTHS (‘31-JAN-96',1) Result Function 01-JUL-03 TRUNC(SYSDATE ,'MONTH') 01-JAN-03 TRUNC(SYSDATE ,'YEAR') 01-AUG-03 ROUND(SYSDATE,'MONTH') 01-JAN-04 ROUND(SYSDATE ,'YEAR')
    • 转换函数 隐式转换 显式转换 数据类型转换
    • 数据类型的隐式转换 NUMBER VARCHAR2 or CHAR DATE VARCHAR2 or CHAR To From VARCHAR2 or CHAR NUMBER VARCHAR2 or CHAR DATE To From … where hire_date > '01-JAN-90' … where name_varchar > 2345 不建议使用隐式转换,可能导致 SQL 的性能下降
    • 数据类型的显式转换 数字类型 字符类型 TO_CHAR() TO_NUMBER() 日期类型 TO_CHAR() TO_DATE()
    • 日期转换为字符 SELECT last_name, TO_CHAR(hire_date, 'fmDD Month YYYY') AS HIREDATE FROM employees; …
    • 数字转换为字符 SELECT TO_CHAR(salary, '$99,999.00') SALARY FROM employees WHERE last_name = 'Ernst';
    • 字符转换为日期、数字 SQL> select TO_number('6,000.00','99,999.00') from dual; TO_NUMBER('6,000.00','99,999.00') --------------------------------- 6000 SQL> select TO_date('20110818','YYYYMMDD') from dual; TO_DATE('201 ------------ 18-AUG-11
    • 函数嵌套
        • 单行函数可以嵌套到任意层。
        • 函数的运算顺序是从内到外。
      F3( F2 ( F1(col,arg1) , arg2 ),arg3) Step 1 = Result 1 Step 2 = Result 2 Step 3 = Result 3
    • 一般函数
        • 下面的函数与 NULL 值的使用有关 :
      函数 含义
          • NVL (expr1, expr2)
      如果 expr1 为 null ,则返回 expr2
          • NVL2 (expr1, expr2, expr3)
      如果 expr1 不为 null ,则返回 expr2 ;如果 expr1 为 null ,则返回 expr3
          • NULLIF (expr1, expr2)
      如果 expr1 与 expr2 相同,则返回 null ,否则返回 expr1
          • COALESCE (expr1, expr2, ..., exprn)
      按顺序判断 expr1~n ,返回首个不为 null 的表达式的值
    • 条件表达式 Conditional Expressions
        • IF-THEN-ELSE 的逻辑判断
        • 有两种方法:
          • CASE
          • DECODE
      CASE expr WHEN comparison_expr1 THEN return_expr1 [WHEN comparison_expr2 THEN return_expr2 WHEN comparison_exprn THEN return_exprn ELSE else_expr ] END DECODE( col|expression, search1, result1 [ , search2, result2,..., ] [ , default ])
    • 组函数
      • 对各组的数据行进行运算,每组返回一个值
      EMPLOYEES Maximum salary in EMPLOYEES table …
    • 组函数类型
      • 对各组的数据行进行运算,每组返回一个值
        • AVG
        • COUNT
        • MAX
        • MIN
        • STDDEV( 平均差 )
        • SUM
        • VARIANCE( 方差 )
      组函数
    • 数据分组 GROUP BY 表 EMPLOYEES … 在 EMPLOYEES 表中,计算每个部门的平均工资 SELECT column , group_function(column) FROM table [WHERE condition ] [GROUP BY group_by_expression ] [ORDER BY column ]; 4400 9500 3500 6400 10033
    • 多个列的 GROUP BY SELECT department_id dept_id, job_id, SUM(salary) FROM employees GROUP BY department_id, job_id ORDER BY department_id;
    • 组函数的使用
      • 在 SELECT 子句中没有使用组函数的数据列,必须在 GROUP BY 子句中列出 :
      SELECT department_id, COUNT(last_name) FROM employees; SELECT department_id, job_id, COUNT(last_name) FROM employees GROUP BY department_id;
    • 组函数的使用
      • 不能在 WHERE 子句中限制组,需要使用 HAVING 。
      • 不能在 WHERE 子句中使用组函数。
      错误: SELECT department_id, AVG(salary) FROM employees WHERE AVG(salary) > 8000 GROUP BY department_id; 正确: SELECT department_id, AVG(salary) FROM employees GROUP BY department_id HAVING AVG(salary) > 8000 ;
    • 组函数的嵌套 SELECT MAX(AVG(salary)) FROM employees GROUP BY department_id;
    • 多个表的数据查询
    • SQL:1999 标准中的 JOIN 语法
      • 使用 join 从多个表中查询数据:
          • table1.column 表示表 table1 中的列名
          • NATURAL JOIN 用于对两个表中相同的列进行 join
          • JOIN table2 USING column_name 基于指定的列进行对等 join
          • JOIN table2 ON table1.column_name = table2.column_name 基于 on 条件指定的列进行对等 join
          • LEFT/RIGHT/FULL OUTER 用于外连接
          • CROSS JOIN 进行笛卡尔乘积
      SELECT table1.column, table2.column FROM table1 [ NATURAL JOIN table2 ] | [ JOIN table2 USING ( column_name )] | [JOIN table2 ON ( table1.column_name = table2.column_name )]| [ LEFT|RIGHT|FULL OUTER JOIN table2 ON ( table1.column_name = table2.column_name )]| [ CROSS JOIN table2 ];
    • NATURAL JOIN
      • NATURAL JOIN 基于两个表中所有相同的列
      • 返回两个表中相同的列的值相同的数据行
      • 如果两个表中,名字相同的列的数据类型定义不同,那么会返回错误
    • 使用 USING 进行 join
      • 如果两个表中的列名相同,但数据类型不同,那么可以使用 using 进行对等 join.
      • 使用 USING 只能指定的一个名字相同的列
    • 使用 ON 进行 join
      • 使用 ON 可以指定任意的条件或相关的列进行 join.
      • 使用 ON 可以增加语句的易读性。
      SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e JOIN departments d ON (e.department_id = d.department_id);
    • 使用 ON 进行 join SELECT employee_id, city, department_name FROM employees e JOIN departments d ON d.department_id = e.department_id JOIN locations l ON d.location_id = l.location_id; …
    • 额外条件 SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e JOIN departments d ON (e.department_id = d.department_id) AND e.manager_id = 149 ;
      • 如要使用额外条件,可以使用 AND 或 WHERE 子句:
      SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e JOIN departments d ON (e.department_id = d.department_id) WHERE e.manager_id = 149 ; 或
    • 自连接 self-join
      • 自连接是指一个表与自己进行 join
      SELECT worker.last_name emp, manager.last_name mgr FROM employees worker JOIN employees manager ON (worker.manager_id = manager.employee_id); … 表 EMPLOYEES 查询结果
    • 非对等连接 Nonequijoins SELECT e.last_name, e.salary, j.grade_level FROM employees e JOIN job_grades j ON e.salary BETWEEN j.lowest_sal AND j.highest_sal; …
    • 外连接 Outer Joins EMPLOYEES DEPARTMENTS There are no employees in department 190. …
    • 内连接和外连接
      • 在 SQL:1999 标准中,只返回匹配记录的 JOIN 称为内连接 (inner join)
      • 除返回匹配记录的结果外,还要从左边 ( 右边 ) 的表中返回不相匹配的数据记录的 join 称为左外 ( 右外 ) 连接 (left /right outer join)
      • 既返回内连接的结果,又返回左外连接与右外连接的 join 称为全外连接 (full outer join)
      • 外连接种类:
          • LEFT OUTER
          • RIGHT OUTER
          • FULL OUTER
    • 左外连接 Left Outer Join SELECT e.last_name, e.department_id, d.department_name FROM employees e LEFT OUTER JOIN departments d ON (e.department_id = d.department_id) ; …
    • 全外连接 Left Outer Join SELECT e.last_name, d.department_id, d.department_name FROM employees e FULL OUTER JOIN departments d ON (e.department_id = d.department_id) ; …
    • 笛卡尔乘积 Cartesian Products
      • 以下情况会进行笛卡尔乘积 :
        • 没有 join 条件
        • Join 条件无效
        • 所有数据都符合 join 条件
      • 尽量避免笛卡尔乘积
    • 子查询 subquery
      • 问题:谁的工资比员工 A 高 ?
      哪个员工的工资比员工 A 高 ? 主查询 : 员工 A 的工资是多少 ? 子查询 :
    • 子查询语法
        • 子查询首先运行
        • 子查询的结果被主查询使用
        • 子查询放于小括号中
        • 单行操作符必须与单行子查询匹配
        • 多行操作符必须与多行子查询匹配
      SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table );
    • Exists
        • EXISTS 测试子查询是否具有相关的数据行
        • 如果找到相关数据行 :
          • 子查询停止运行
          • 返回结果为 TRUE
        • 如果没有找到相关数据行 :
          • 返回结果为 FALSE
          • 继续子查询,直到子查询结束
    • NOT Exists 和 NOT in
        • 如果子查询返回 NULL 值,则 NOT IN 返回假
        • 当没有 null 值时 NOT in 与 not exists 效果相同
      SELECT department_id, department_name FROM departments d WHERE NOT EXISTS (SELECT 'X' FROM employees WHERE department_id = d.department_id); 查找哪个部门没有员工 ( 表 employees 中有一行数据的 department_id 为 null )
      • SELECT department_id, department_name
      • FROM departments d
              • WHERE department_id NOT IN (SELECT department_id
              • FROM employees);
      No rows selected.
    • IN 、 ANY 、 ALL
        • <ANY 意谓着小于子查询返回结果的最大值
        • >ANY 意谓着大于子查询结果的最小值
        • =ANY 和 IN 的效果相同
        • ANY 中的子查询如果返回 0 行,则 <ANY , >ANY , =ANY , !=ANY , <=ANY 等操作都判断为假,主查询不返回数据
      SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary < ANY (SELECT salary FROM employees WHERE job_id = 'IT_PROG') AND job_id <> 'IT_PROG';
    • IN 、 ANY 、 ALL
        • <ALL 意谓着小于子查询返回结果的最小值
        • >ALL 意谓着大于子查询结果的最大值
        • ALL 中的子查询如果返回 0 行,则 <ALL , >ALL , =ALL , !=ALL , <=ALL 等操作都判断为真,主查询返回符合其他条件的数据
      SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary < ALL (SELECT salary FROM employees WHERE job_id = 'IT_PROG') AND job_id <> 'IT_PROG';
    • 集合操作符 Set Operators UNION / UNION ALL A B A B A B INTERSECT A B MINUS
    • 集合操作符说明
      • 两个查询语句中引用的列数量要一致
      • 第二个查询的列的数据类型须要与第一个查询的列一一对应
      • 可以使用括号改变执行顺序
      • 除 UNION ALL 外,重复行只显示一次
      • 列名的显示以第一个查询为准
      • 默认情况下,除 UNION ALL 外,查询结果以升序排序
    • UNION SELECT employee_id, job_id FROM employees UNION SELECT employee_id, job_id FROM job_history; … …
    • UNION ALL SELECT employee_id, job_id, department_id FROM employees UNION ALL SELECT employee_id, job_id, department_id FROM job_history ORDER BY employee_id; … …
    • INTERSECT SELECT employee_id, job_id FROM employees INTERSECT SELECT employee_id, job_id FROM job_history;
    • MINUS SELECT employee_id FROM employees MINUS SELECT employee_id FROM job_history; …
    • 列数量与类型匹配 SELECT location_id , department_name &quot;Department&quot; , TO_CHAR(NULL) &quot;Warehouse location&quot; FROM departments UNION SELECT location_id, TO_CHAR(NULL) &quot;Department&quot; , state_province FROM locations;
    • 集合操作符与 ORDER BY
      • ORDER BY 只能在整个查询的最后面出现一次
      • ORDER BY 中指定的列,必须在第一个查询语句中指定的列
      • 默认情况下,第一个查询语句中的第一个列作为返回结果的排序依据,顺序为升序
    • 多列子查询 Multiple-Column Subqueries 主查询 WHERE ( MANAGER_ID, DEPARTMENT_ID ) IN 子查询结果 100 90 102 60 124 50
    • 多列子查询 Multiple-Column Subqueries
        • 不成对比较
        • 成对比较
    • 成对比较子查询 返回与名字为 John 的员工在同一个部门,且同一个领导的员工 SELECT employee_id, manager_id, department_id FROM empl_demo WHERE (manager_id, department_id) IN (SELECT manager_id, department_id FROM empl_demo WHERE first_name = 'John') AND first_name <> 'John';
    • 不成对比较子查询 返回与名字为 John 的员工中任意一个领导相符和任意一个部门相符的员工 当名字为 John 多于一人时,与成对比较子查询的返回结果不同。 SELECT employee_id, manager_id, department_id FROM empl_demo WHERE manager_id IN (SELECT manager_id FROM empl_demo WHERE first_name = 'John') AND department_id IN (SELECT department_id FROM empl_demo WHERE first_name = 'John') AND first_name <> 'John';
    • 关联子查询 关联子查询用于行与行的处理,关联子查询对每个数据行都要进行 一次。 GET 主查询 fetch 到一行数据 EXECUTE 子查询根据这行数据的值进行运算 USE 根据子查询的结果,决定是否返回这行数据
    • 关联子查询 vs 嵌套子查询 嵌套子查询: 子查询首先执行,且执行一次,返回相关结果 主查询使用子查询返回的结果进行一次运算 关联子查询: 主查询 fetch 到一行数据 根据这行数据,进行子查询运算 根据子查询的结果,决定是否返回这行数据 重复以上过程,直到主查询结束
    • 使用关联子查询 SELECT column1 , column2 , ... FROM table1 WHERE column1 operator (SELECT column1, column2 FROM table2 WHERE expr1 = .expr2 ); outer outer SELECT e.employee_id, last_name,e.job_id FROM employees e WHERE 2 <= (SELECT COUNT(*) FROM job_history WHERE employee_id = e.employee_id );
    • WITH
        • 使用 WITH ,可以在查询中多次引用相同的子查询
        • 使用 WITH 返回的结果存放在临时空间
        • 在复杂的查询中适当使用 WITH ,可以提高性能
    • WITH 示例 WITH dept_costs AS ( SELECT d.department_name, SUM(e.salary) AS dept_total FROM employees e JOIN departments d ON e.department_id = d.department_id GROUP BY d.department_name), avg_cost AS ( SELECT SUM(dept_total)/COUNT(*) AS dept_avg FROM dept_costs ) SELECT * FROM dept_costs WHERE dept_total > (SELECT dept_avg FROM avg_cost ) ORDER BY department_name;
    • 处理数据
    • DML Data Manipulation Language
      • DML 的作用 :
        • 添加新的数据到表中
        • 修改表中已有的数据
        • 删除表中已有的数据
      • 事务:由一系列的 DML 语句组成,成为一个逻辑工作单元。事务中的语句必须全部成功,否则必须全部回退。
    • INSERT INSERT INTO departments VALUES (100, 'Finance', NULL, NULL); INSERT INTO departments (department_id, department_name) VALUES (30, 'Purchasing'); INSERT INTO sales_reps(id, name, salary, commission_pct) SELECT employee_id, last_name, salary, commission_pct FROM employees INSERT INTO employees (employee_id,hire_date) VALUES (113,SYSDATE);
    • 多表 INSERT
      • 多表插入有以下种类 :
      • 无条件 INSERT
      • 有条件 INSERT ALL
      • 旋转 (Pivoting) INSERT
      • 条件 INSERT FIRST
    • Unconditional INSERT ALL INSERT ALL INTO sal_history VALUES(EMPID,HIREDATE,SAL) INTO mgr_history VALUES(EMPID,MGR,SAL) SELECT employee_id EMPID, hire_date HIREDATE, salary SAL, manager_id MGR FROM employees WHERE employee_id > 200;
    • Unconditional INSERT ALL INSERT ALL INTO sal_history VALUES(EMPID,HIREDATE,SAL) INTO mgr_history VALUES(EMPID,MGR,SAL) SELECT employee_id EMPID, hire_date HIREDATE, salary SAL, manager_id MGR FROM employees WHERE employee_id > 200;
    • Conditional INSERT ALL INSERT ALL WHEN HIREDATE < ' 01-JAN-95 ' THEN INTO emp_history VALUES(EMPID,HIREDATE,SAL) WHEN COMM IS NOT NULL THEN INTO emp_sales VALUES(EMPID,COMM,SAL) SELECT employee_id EMPID, hire_date HIREDATE, salary SAL, commission_pct COMM FROM employees
    • Conditional INSERT FIRST INSERT FIRST WHEN salary < 5000 THEN INTO sal_low VALUES (employee_id, last_name, salary) WHEN salary between 5000 and 10000 THEN INTO sal_mid VALUES (employee_id, last_name, salary) ELSE INTO sal_high VALUES (employee_id, last_name, salary) SELECT employee_id, last_name, salary FROM employees
    • Pivoting INSERT
      • 行列转换
      6000 5000 4000 3000 2000 6 176 FRI THUR WED TUES MON Week_ID Emp_ID 6000 6 176 5000 6 176 4000 6 176 3000 6 176 2000 6 176 SALES WEEK Employee_ID
    • Pivoting INSERT INSERT ALL INTO sales_info VALUES (employee_id,week_id,sales_MON) INTO sales_info VALUES (employee_id,week_id,sales_TUE) INTO sales_info VALUES (employee_id,week_id,sales_WED) INTO sales_info VALUES (employee_id,week_id,sales_THUR) INTO sales_info VALUES (employee_id,week_id, sales_FRI) SELECT EMPLOYEE_ID, week_id, sales_MON, sales_TUE, sales_WED, sales_THUR,sales_FRI FROM sales_source_data;
    • UPDATE UPDATE employees SET department_id = 50 WHERE employee_id = 113; UPDATE copy_emp SET department_id = 110; UPDATE employees SET department_id = 50 WHERE employee_id = null; UPDATE employees SET job_id = (SELECT job_id FROM employees WHERE employee_id = 205) WHERE employee_id = 113;
    • UPDATE 中的关联子查询 UPDATE table1 alias1 SET column = (SELECT expression FROM table2 alias2 WHERE alias1.column = alias2.column );
    • DELETE DELETE FROM departments WHERE department_name = ‘Finance'; DELETE FROM copy_emp; DELETE FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name LIKE '%Public%');
    • DELETE 中的关联子查询 DELETE FROM table1 alias1 WHERE column operator (SELECT expression FROM table2 alias2 WHERE alias1.column = alias2.column);
    • TRUNCATE TRUNCATE TABLE table_name ;
      • 清空表中的所有数据
      • 删除数据的效率明显比 DELETE 高
      • 恢复数据需要备份,代价高
    • 事务
      • 事务由以下中的一种组成:
      • DML 语句
      • DDL 语句
      • DCL 语句
    • 事务的开始与结束
      • 开始于第一个被执行的 DML 语句
      • 结束于以下其中一个事件 :
            • COMMIT 或 ROLLBACK 被运行
            • DDL 或 DCL 被执行 ( 自动 commit)
            • 用户正常退出 ( 自动 commit)
            • 用户非正常退出 ( 自动 rollback)
            • 系统异常中止 ( 自动 rollback)
    • 事务的显式控制 SAVEPOINT B SAVEPOINT A DELETE INSERT UPDATE INSERT COMMIT 时间轴 Transaction ROLLBACK to SAVEPOINT B ROLLBACK to SAVEPOINT A ROLLBACK
    • Commit 或 Rollback 前的数据状态
      • 事务中的被修改的数据可以被恢复
      • 事务的发起者可以使用 SELECT 复查数据的修改结果
      • 事务中的数据修改对其他用户不可见
      • 被修改的数据行被锁定,其他用户不能进行修改
    • Commit 后的数据状态
      • 数据的修改被保存
      • 以前的数据被覆盖
      • 所有用户可以看到修改的结果
      • 被修改数据上的锁被释放,其他用户可以进行修改
      • 所有 savepoint 被清除
    • Rollback 后的数据状态
      • 数据修改被回滚
      • 数据恢复到事务前的状态
      • 锁被释放
    • 语句级回滚 Statement-Level Rollback
      • 当一个单独的 DML 在执行时失败,那么只有这个语句被回滚
      • 数据库自动进行隐式的 savepoint
      • 事务中之前的数据修改不被回滚
    • 读一致性 Read Consistency
      • 读一致性确保在任意时间点,数据库都能提供数据的一致性视图
      • 读一致性要求对于同一份数据 :
        • 查询不需要等待修改
        • 修改不需要等待查询
        • 修改需要等待修改
    • 读一致性的实现 SELECT * FROM userA.employees; UPDATE employees SET salary = 7000 WHERE last_name = 'Grant'; Data blocks Undo segments Changed and unchanged data Before change (“old” data) 用户 A 用户 B Read- consistent image
    • SELECT 中的 FOR UPDATE 子句
      • 锁定符合条件的数据行
      • 锁可以被 COMMIT 或 ROLLBACK 释放
      • 当有一个用户正在修改数据,而另一个用户进行 SELECT FOR UPDATE 去查询这部分数据时,会进行等待,直到第一个用户释放锁。
      • 在多表查询时,使用 for update of table1.column_name 时,只有指定列相关的表的一部分符合条件数据被锁定。
      SELECT employee_id, salary, commission_pct, job_id FROM employees WHERE job_id = 'SA_REP' FOR UPDATE ORDER BY employee_id;
    • 创建数据库对象
    • 数据库对象 逻辑上代表一个或多个表的数据子集 View 产生单调递增的数值 Sequence 存放数据行的逻辑存储单元 Table 同义词,一个对象的替代名称 Synonym 用于改进查询性能 Index 描述 对象
    • 表的命名规则
      • 表名或列名 :
      • 必须以字母开头
      • 长度为 1–30
      • 只能包含 A–Z, a–z, 0–9, _, $, #
      • 同一个用户下的名字不能重复
      • 不能是 ORACLE 系统的保留字
    • CREATE TABLE
      • 创建表必须满足 :
      • 拥有 CREATE TABLE 权限
      • 拥有存储空间额度
      • 需要指定 :
      • 表名
      • 列名,列的数据类型,列长
      CREATE TABLE [ schema .] table ( column datatype [DEFAULT expr ][, ...]);
    • CREATE TABLE DESCRIBE dept CREATE TABLE dept (deptno NUMBER(2), dname VARCHAR2(14), loc VARCHAR2(13), create_date DATE DEFAULT SYSDATE );
    • 引用其他用户的表 USERB USERA SELECT * FROM userB.employees; SELECT * FROM userA.employees;
    • CTAS (Create Table As Select) CREATE TABLE dept80 AS SELECT employee_id, last_name, salary*12 ANNSAL, hire_date FROM employees WHERE department_id = 80; DESCRIBE dept80
    • 数据类型 未经处理的类型 RAW and LONG RAW 二进制数据类型 (up to 4 GB) BLOB 存储在外部文件的二进制数据类型 (up to 4 GB) BFILE 日期类型 DATE 变长的字符类型 (up to 2 GB) LONG 字符类型 (up to 4 GB) CLOB 代表表中数据行的唯一地址 ROWID 定长的字符数据 CHAR( size ) 变长的数值类型 NUMBER( p , s) 变长的字符类型 VARCHAR2( size ) 描述 Data Type
    • 数据类型 存储时间间隔的类型 INTERVAL YEAR TO MONTH 存储时间间隔的类型 INTERVAL DAY TO SECOND 较精细的日期类型 TIMESTAMP 描述 Data Type
    • 约束 Constraints
      • 约束增强表级规则
      • 如果有依赖关系,约束阻止数据删除
      • 下列约束类型是有效的 :
        • NOT NULL
        • UNIQUE
        • PRIMARY KEY
        • FOREIGN KEY 引用其他表的列值
        • CHECK
    • 约束 Constraints
      • 用户可以指定约束的名称,或者由数据库自动生成格式为 SYS_C n 的名字
      • 可以在以下情况创建约束 :
          • 在表的创建时
          • 在表的创建后
      • 可以在列级或表级定义约束
      • 可以通过数据字典查询约束的详细定义 .
    • 约束 Constraints
      • 语法
      • 列级约束
      • 表级约束
      CREATE TABLE [ schema .] table ( column datatype [DEFAULT expr ] [ column_constraint ], ... [ table_constraint ][,...] ); column,... [CONSTRAINT constraint_name ] constraint_type ( column , ...), column [CONSTRAINT constraint_name ] constraint_type ,
    • 约束 Constraints
      • 列级约束
      • 表级约束
      CREATE TABLE employees( employee_id NUMBER(6) CONSTRAINT emp_emp_id_pk PRIMARY KEY, first_name VARCHAR2(20), ...); CREATE TABLE employees( employee_id NUMBER(6), first_name VARCHAR2(20), ... job_id VARCHAR2(10) NOT NULL, CONSTRAINT emp_emp_id_pk PRIMARY KEY (EMPLOYEE_ID) ); 1 2
    • 外键约束 FOREIGN KEY Constraint 部门表 员工表 外键 INSERT INTO 操作 允许 ( 部门表的主键列不存在数值 9) 允许 主键 … …
    • 外键约束 FOREIGN KEY Constraint
        • FOREIGN KEY (referential integrity) 约束将一个列或几个列的组合作为一个外键,这个外键与同一个表或另一个表的主键或唯一键建立参考关系
        • 外键所在表称为子表 (child table) ,被参考的主键或唯一键所在的表称为父表 (parent table)
        • 一个外键的值必须与父表中存在的值匹配,或者为 NULL
      CREATE TABLE employees( employee_id NUMBER(6), last_name VARCHAR2(25) NOT NULL, email VARCHAR2(25), salary NUMBER(8,2), commission_pct NUMBER(2,2), hire_date DATE NOT NULL, ... department_id NUMBER(4), CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES departments(department_id), CONSTRAINT emp_email_uk UNIQUE(email));
    • 外键约束 FOREIGN KEY Constraint
        • FOREIGN KEY :定义外键
        • REFERENCES : 定义父表中的主键或唯一键
        • ON DELETE CASCADE : 当父表中的一行数据被删除的同时,也删除子表中 的相关数据行。
        • ON DELETE SET NULL : 当父表中的一行数据被删除的同时,将子表中 的相关数据置为 NULL 。
    • CHECK 约束 CHECK Constraint
        • 定义一个每行数据必须满足的条件,但以下表达式不能使用:
          • CURRVAL , NEXTVAL , LEVEL 和 ROWNUM 伪列
          • SYSDATE , UID , USER 和 USERENV 函数
          • 与其他行的其他数值相关的查询
        • 一个列上可以定义多个 CHECK 约束
      ..., salary NUMBER(2) CONSTRAINT emp_salary_min CHECK (salary > 0),...
    • Alter Table 语句
        • ALTER TABLE 的作用 :
        • 增加一个列
        • 修改一个列的定义
        • 定义一个新列的默认值
        • 删除一个列
        • 重命名一个列的名称
        • 将表置为 read-only , read-write 状态
      ALTER TABLE employees READ ONLY; ALTER TABLE employees READ WRITE;
    • Drop Table 语句
        • DROP TABLE 的作用 :
        • 将表移动到回收站 (recyclebin)
        • 使有依赖关系的数据库对象失效
        • 移除相关权限
      DROP TABLE dept80;
    • 创建其他对象 逻辑上显示一个或多个表的数据子集,不占用存储空间 View 产生单调递增的数值 Sequence 由数据行组成,基本的存储单元 Table 同义词,一个对象的替代名称 Synonym 增强查询性能 Index 描述 对象
    • 视图 VIEW
        • 简单视图与复杂视图:
      Yes No No One Simple Views Yes 包含函数 Yes 使用 group by One or more 相关表的个数 Not always 通过视图进行 DML 操作 Complex Views 特点
    • 创建视图 CREATE [OR REPLACE] [FORCE| NOFORCE ] VIEW view [( alias [, alias ]...)] AS subquery [WITH CHECK OPTION [CONSTRAINT constraint ]] [WITH READ ONLY [CONSTRAINT constraint ]]; CREATE OR REPLACE VIEW empvu80 (id_number, name, sal, department_id) AS SELECT employee_id, first_name || ' ' || last_name, salary, department_id FROM employees WHERE department_id = 80;
    • 对视图进行 DML 操作的规则
        • 对简单视图总是可以进行 DML 操作
        • 如果视图含有以下内容时,不能 删除 数据行 :
          • 组函数 Group functions
          • 有 GROUP BY 子句
          • 有 DISTINCT
          • 有伪列 ROWNUM
    • 对视图进行 DML 操作的规则
        • 如果视图含有以下内容时,不能 修改 数据行 :
          • 组函数 Group functions
          • 有 GROUP BY 子句
          • 有 DISTINCT
          • 有伪列 ROWNUM
          • 以表达式定义的列 (for example, SALARY * 12 )
    • 对视图进行 DML 操作的规则
        • 如果视图含有以下内容时,不能 插入 数据行 :
          • 组函数 Group functions
          • 有 GROUP BY 子句
          • 有 DISTINCT
          • 有伪列 ROWNUM
          • 以表达式定义的列 (for example, SALARY * 12 )
          • 基表中的 NOT NULL 列在视图中不可见时
    • 使用 WITH CHECK OPTION
        • WITH CHECK OPTION 可以限制 DML 操作 :
      CREATE OR REPLACE VIEW empvu20 AS SELECT * FROM employees WHERE department_id = 20 WITH CHECK OPTION CONSTRAINT empvu20_ck ;
    • 使用 WITH READ ONLY
        • WITH READ ONLY 选项防止 DML 操作
      CREATE OR REPLACE VIEW empvu10 (employee_number, employee_name, job_title) AS SELECT employee_id, last_name, job_id FROM employees WHERE department_id = 10 WITH READ ONLY ;
    • 删除视图
        • 删除视图对基表没有影响,不会丢失数据
      DROP VIEW view ; DROP VIEW empvu80;
    • 序列 Sequences
        • 序列可以:
        • 可以自动生成具有唯一性的数值
        • 是可共享对象
        • 可以用于创建主键值
        • 可以替代相同功能的自定义程序
        • 当设置 CACHE 时,可以增加效率
      1 2 4 3 5 6 8 7 10 9
    • 创建序列 CREATE SEQUENCE sequence [INCREMENT BY n ] [START WITH n ] [{MAXVALUE n | NOMAXVALUE }] [{MINVALUE n | NOMINVALUE }] [{CYCLE | NOCYCLE }] [{CACHE n | NOCACHE}];
    • NEXTVAL 和 CURRVAL
        • NEXTVAL 返回下一个可用的序列值。
        • CURRVAL 返回当前用户的当前的序列值
        • 在使用 CURRVAL 前,必须先使用 NEXTVAL 生成一个序列值
    • 使用序列
        • 插入一个新的部门“ Support” , location_ID 为 2500:
        • 查看序列 DEPT_DEPTID_SEQ 的当前值
      INSERT INTO departments(department_id, department_name, location_id) VALUES ( dept_deptid_seq.NEXTVAL , 'Support', 2500); SELECT dept_deptid_seq.CURRVAL FROM dual;
    • 缓存序列值
        • 缓存序列值增加性能
        • 序列值间断 (gap) 在以下情况出现:
          • 发生 rollback
          • 系统异常关闭
          • 序列值被用于另一个表
    • 修改序列 ALTER SEQUENCE dept_deptid_seq INCREMENT BY 20 MAXVALUE 999999 NOCACHE NOCYCLE;
        • 只有以后的序列值受影响
        • 如果要更改起始值,只能重新创建序列
        • 会进行一些验证
        • 要删除序列,使用 DROP 语句 :
      DROP SEQUENCE dept_deptid_seq;
    • 索引 Indexes
        • 索引:
        • 是一个用户对象
        • 增加性能
        • 快速定位数据,降低磁盘 IO
        • 索引可以被更改或删除,而不影响表和其他索引的数据
        • 创建完成后,数据库自动使用与维护索引
    • 索引是怎样被创建的?
        • 自动 : 当定义了一个主键或唯一性键时,唯一性索引可以被自动创建。
        • 手动 : 除了唯一性索引,用户还可以创建非唯一性索引
    • 创建索引
        • 在一个或多个列上创建索引 :
        • 以下索引可以根据 last_name 列的条件,加快查询:
      CREATE INDEX emp_last_name_idx ON employees(last_name); CREATE [UNIQUE][BITMAP]INDEX index ON table ( column [, column ]...);
    • 索引创建建议 以下情况时,不要创建索引 :
        • 查询条件中不常出现的列
        • 表很小,或者大多数查询涉及的数据大于 4%
        • 更新频繁的表
        • 一个列的值拥有大量的 NULL 值
        • 一个或多个列经常在 WHERE 子句或 join 条件中被引用
        • 一个列的值较宽泛,范围大
        • 需要引用的列包含在表达式中
        • 表非常大,绝大多数的查询涉及的数据小于 4%
      以下情况时,创建索引 :
    • 删除索引
        • DROP INDEX :
        • 删除 emp_last_name_idx :
        • 删除索引,需要是索引的所有者,或者有 DROP ANY INDEX 系统权限 .
      DROP INDEX emp_last_name_idx; DROP INDEX index ;
    • 同义词 Synonym
        • 同义词可以 :
        • 引用其他用户下的表时更方便
        • 相对于原表,缩短引用表名所需长度
      CREATE [PUBLIC] SYNONYM synonym FOR object ;
    • 创建和删除同义词
        • 创建更短的名字 :
        • 删除同义词 :
        • 不影响原对象
      CREATE SYNONYM d_sum FOR dept_sum_vu; DROP SYNONYM d_sum;
    • 控制用户访问
    • 控制用户访问 DB 管理员 用户 用户名、密码 权限
    • 权限 Privileges
        • 系统权限 : 用于在数据库内进行特定的操作
        • 对象权限 : 处理数据库对象的内容
        • Schemas: 对象的集合,如 tables, views, and sequences
    • 系统权限
        • 超过 100 个系统权限
        • 数据库管理员拥有高级的系统权限,如:
          • 创建新用户
          • 删除用户
          • 删除表
          • 备份表
    • 创建用户 CREATE USER demo IDENTIFIED BY demo; CREATE USER user IDENTIFIED BY password ;
    • 用户系统权限
        • 在用户被创建后,管理员可以将权限赋于用户 .
        • 比如一个程序开发用户,可以有以下权限 :
          • CREATE SESSION
          • CREATE TABLE
          • CREATE SEQUENCE
          • CREATE VIEW
          • CREATE PROCEDURE
      GRANT privilege [, privilege ...] TO user [, user| role, PUBLIC ...]; GRANT create session, create table, create sequence, create view TO demo;
    • 角色 Roles 不使用 roles 进行权限分配 使用 roles 进行权限分配 权限 用户 Manager
    • 创建角色 CREATE ROLE manager; GRANT create table, create view TO manager; GRANT manager TO BELL, KOCHHAR;
    • 对象权限 对象 权限 表 视图 序列 ALTER DELETE INDEX INSERT REFERENCES SELECT UPDATE
    • 对象权限
        • 不同类型的对象有其自身的对象权限
        • 对象的所有者拥有这个对象的全部权限
        • 所有者可以将对象权限赋予其他用户
      GRANT object_priv [( columns )] ON object TO { user | role |PUBLIC} [WITH GRANT OPTION];
    • 赋予对象权限
        • 将查询 EMPLOYEES 的权限赋予 demo 用户 :
        • 将特定列的 UPDATE 权限赋予用户和角色:
      GRANT select ON employees TO demo; GRANT update (department_name, location_id) ON departments TO demo, manager;
    • 回收对象权限
        • 使用 REVOKE 收回权限
        • 通过 WITH GRANT OPTION 赋给其他用户的权限也同时收回 .
      REVOKE {privilege [, privilege...]|ALL} ON object FROM {user[, user...]|role|PUBLIC} [CASCADE CONSTRAINTS];