Oracle select总结
- sql初步
- 基本SQL SELECT
- 过滤和排序数据
- 单 行 函 数
- 多 表 查 询
- 分 组 函 数
- 子 查 询
sql初步
sql语句分为以下3种类型:
-
DML 数据操作语言
-
DML用于查询与修改数据记录,包括如下SQL语句:
lINSERT:添加数据到数据库中
lUPDATE:修改数据库中的数据
lDELETE:删除数据库中的数据
lSELECT****:选择(查询)数据
ØSELECT是SQL语言的基础,最为重要。
-
-
DDL数据定义语言
-
DDL用于定义数据库的结构,比如创建、修改或删除数据库对象,包括如下SQL语句:
lCREATE TABLE:创建数据库表
lALTER TABLE:更改表结构、添加、删除、修改列长度
lDROP TABLE:删除表
lCREATE INDEX:在表上建立索引
lDROP INDEX:删除索引
-
-
DCL数据控制语言
-
DCL用来控制数据库的访问,包括如下SQL语句:
lGRANT:授予访问权限
lREVOKE:撤销访问权限
lCOMMIT:提交事务处理
lROLLBACK:事务处理回退
lSAVEPOINT:设置保存点
lLOCK:对数据库的特定部分进行锁定
-
基本SQL SELECT
select查询顺序
select 字段
from 表1 别名
连接类型 join 表2 别名
on 连接条件
where 条件1
group by 分组字段
having 条件2(一般是分组条件)
order by 排序字段 (desc/asc)
limit 索引,最大查询数量;
选择全部列
SELECT * FROM departments;
选择特定的列
SELECT department_id, location_id FROM departments;
算术运算符
数字和日期使用的算术运算符。
+ - * / 加 减 乘 除
使用数学运算符
SELECT last_name, salary, salary + 300 FROM employees;
操作符优先级
* / + - 乘 除 加 减
乘除的优先级高于加减。
同一优先级运算符从左向右执行。
括号内的运算先执行
操作符优先级
SELECT last_name, salary, 12*salary+100 FROM employees;
使用括号
SELECT last_name, salary, 12*(salary+100) FROM employees;
定义空值
空值是无效的,未指定的,未知的或不可预知的值
空值不是空格或者0。
空值在数学运算中的使用
包含空值的数学表达式的值都为空值
列的别名
重命名一个列。
便于计算。
紧跟列名,也可以在列名和别名之间加入关键字‘AS’,别名使用双引号,以便在别名中包含空格或特殊的字符并区分大小写。
使用别名
SELECT last_name AS name, commission_pct comm FROM employees;
SELECT last_name "Name", salary*12 "Annual Salary" FROM employees;
连接符
把列与列,列与字符连接在一起。
用 ‘||’表示。
可以用来‘合成’列。
连接符应用举例
SELECT last_name||job_id AS "Employees" FROM employees;
字符串
字符串可以是 SELECT 列表中的一个字符,数字,日期。
日期和字符只能在单引号中出现。
每当返回一行时,字符串被输出一次。
字符串
SELECT last_name ||' is a '||job_id
AS "Employee Details"
FROM employees;
删除重复行
在 SELECT 子句中使用关键字 ‘DISTINCT’ 删除重复行。
SELECT DISTINCT department_id
FROM employees;
SQL*Plus
描述表结构。
编辑 SQL 语句。
执行 SQL语句。
将 SQL 保存在文件中并将SQL语句执行结果保存在文件中。
在保存的文件中执行语句。
将文本文件装入 SQL*Plus编辑窗口。
注 意 SQL输写
•SQL 语言大小写不敏感。
•SQL 可以写在一行或者多行
•关键字不能被缩写也不能分行
•各子句一般要分行写。
•使用缩进提高语句的可读性。(sql格式化)
过滤和排序数据
过滤
WHERE 子句
使用WHERE 子句,将不满足条件的行过滤掉
WHERE 子句紧随 FROM 子句。
SELECT employee_id, last_name, job_id, department_id
FROM employees
WHERE department_id = 90 ;
字符和日期
字符和日期要包含在单引号中。
字符大小写敏感,日期格式敏感。
默认的日期格式是 DD-MON月-RR。
SELECT last_name, job_id, department_id
FROM employees
WHERE last_name = 'Whalen';
SELECT last_name, hire_date, department_id
FROM employees
WHERE hire_date = '7-6月-1994'
比较运算
操作符含义
= 等于 (不是 ==)
> 大于
>= 大于、等于
< 小于
<= 小于、等于
<> 不等于 (也可以是 !=)
赋值使用 := 符号
比较运算
SELECT last_name, salary
FROM employees
WHERE salary <= 3000;
其它比较运算
操作符 含义
BETWEEN...AND... 在两个值之间 (包含边界)
IN(set) 等于值列表中的一个
LIKE 模糊查询
IS NULL 空值
BETWEEN
使用 BETWEEN 运算来显示在一个区间内的值
SELECT last_name, salary
FROM employees
WHERE salary BETWEEN 2500 AND 3500;
IN
使用 IN运算显示列表中的值。
SELECT employee_id, last_name, salary, manager_id
FROM employees
WHERE manager_id IN (100, 101, 201);
LIKE
使用 LIKE 运算选择类似的值
选择条件可以包含字符或数字:
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
SELECT first_name
FROM employees
WHERE first_name LIKE 'S%';
‘%’和‘-’可以同时使用。
可以使用 ESCAPE 标识符 选择‘%’和 ‘_’ 符号。
SELECT last_name
FROM employees
WHERE last_name LIKE '_o%';
ESCAPE
回避特殊符号的:使用转义符。例如:将[%]转为[\%]、[_]转为[\_],然后再加上[ESCAPE ‘\’] 即可。
SELECT job_id
FROM jobs
WHERE job_id LIKE ‘IT\_%‘ escape ‘\‘;
NULL
使用 IS (NOT) NULL 判断空值
SELECT last_name, manager_id
FROM employees
WHERE manager_id IS NULL;
逻辑运算
操作符 含义
AND 逻辑并
OR 逻辑或
NOT 逻辑否
AND
AND 要求并的关系为真。
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary >=10000
AND job_id LIKE '%MAN%';
OR
OR 要求或关系为真。
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary >= 10000
OR job_id LIKE '%MAN%';
NOT
SELECT last_name, job_id
FROM employees
WHERE job_id
NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP');
优先级
优先级
1 算术运算符
2 连接符
3 比较符
4 IS [NOT] NULL, LIKE, [NOT] IN
5 [NOT] BETWEEN
6 NOT
7 AND
8 OR
可以使用括号改变优先级顺序
ORDER BY子句
使用 ORDER BY 子句排序
ASC(ascend): 升序
DESC(descend): 降序
ORDER BY 子句在SELECT语句的结尾。
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date ;
降序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date DESC ;
按别名排序
SELECT employee_id, last_name, salary*12 annsal
FROM employees
ORDER BY annsal;
多个列排序
按照ORDER BY 列表的顺序排序
可以使用不在SELECT 列表中的列排序。
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
总 结
使用WHERE 子句过滤数据
使用比较运算
使用 BETWEEN AND, IN, LIKE和 NULL运算
使用逻辑运算符 AND, OR和NOT
使用 ORDER BY 子句进行排序。
单 行 函 数
SQL 函数
y = f(x1,…,x2)
输出(输入结果)=函数(输入:参数1,参数2,。。。参数n)
两种SQL函数
函数:单行函数,多行行函数
单行函数
操作数据对象
接受参数返回一个结果
只对一行进行变换
每行返回一个结果
可以转换数据类型
可以嵌套
参数可以是一列或一个值
单行函数
字符,通用,数值,转换,日期
字符函数
大小写控制函数:LOWER,UPPER,INITCAP
字符控制函数:CONCAT,SUBSTR,LENGTH,INSTR,LPAD | RPAD,TRIM,REPLACE
大小写控制函数:这类函数改变字符的大小写。
函数 结果
LOWER('SQL Course') sql course
UPPER('SQL Course') SQL COURSE
INITCAP('SQL Course') Sql Course
SELECT employee_id, last_name, department_id
FROM employees
WHERE LOWER(last_name) = 'higgins';
字符控制函数:这类函数控制字符
函数 结果
CONCAT('Hello', 'World') HelloWorld
SUBSTR('HelloWorld',1,5) Hello
LENGTH('HelloWorld') 10
INSTR('HelloWorld', 'W') 6
LPAD(salary,10,'*') *****24000
RPAD(salary, 10, '*') 24000*****
TRIM('H' FROM 'HelloWorld') elloWorld
REPLACE(‘abcd’,’b’,’m’) amcd
SELECT employee_id, CONCAT(first_name, last_name) NAME,
job_id, LENGTH (last_name),
INSTR(last_name, 'a') "Contains 'a'?"
FROM employees
WHERE SUBSTR(job_id, 4) = 'REP';
数字函数
ROUND: 四舍五入
ROUND(45.926, 2) 45.93
TRUNC: 截断
TRUNC(45.926, 2) 45.92
MOD: 求余
MOD(1600, 300) 100
日 期:函数SYSDATE 返回
日期
时间
日期的数学运算
在日期上加上或减去一个数字结果仍为日期。
两个日期相减返回日期之间相差的天数。
日期不允许做加法运算,无意义
可以用数字除24来向日期中加上或减去天数
日期函数
函数 描述
MONTHS_BETWEEN 两个日期相差的月数
ADD_MONTHS 向指定日期中加上若干月数
NEXT_DAY 指定日期的下一个星期 * 对应的日期
LAST_DAY 本月的最后一天
ROUND 日期四舍五入
TRUNC 日期截断
日期函数
MONTHS_BETWEEN ('01-SEP-95','11-JAN-94') 19.6774194
ADD_MONTHS ('11-JAN-94',6) '11-JUL-94'
NEXT_DAY ('01-SEP-95','FRIDAY') '08-SEP-95'
LAST_DAY('01-FEB-95') '28-FEB-95'
Assume SYSDATE = '25-JUL-95':
ROUND(SYSDATE,'MONTH') 01-AUG-95
ROUND(SYSDATE ,'YEAR') 01-JAN-96
TRUNC(SYSDATE ,'MONTH') 01-JUL-95
TRUNC(SYSDATE ,'YEAR') 01-JAN-95
转换函数
数据类型转换:隐性,显性
隐式数据类型转换
Oracle 自动完成下列转换:
源数据类型 目标数据类型
VARCHAR2 or CHAR NUMBER
VARCHAR2 or CHAR DATE
NUMBER VARCHAR2
DATE VARCHAR2
date <=>varchar2<=>number
TO_DATE函数对日期的转换
必须包含在单引号中而且大小写敏感。
可以包含任意的有效的日期格式。
日期之间用逗号隔开。
SELECT TO_DATE(sysdate,‘yyyy-mm-dd hh:mi:ss’) FROM dual;
日期格式的元素
时间格式: HH24:MI:SS AM | 15:45:32 PM
使用双引号向日期中添加字符:DD "of" MONTH | 12 of OCTOBER
TO_CHAR 函数对字符的转换
使用 TO_CHAR 函数对字符的转换
SELECT TO_CHAR(salary) SALARY
FROM employees
WHERE last_name = 'Ernst';
TO_NUMBER 函数
使用 TO_NUMBER 函数对数字的转换
select TO_NUMBER(‘¥1,234,567,890.00’,’L999,999,999,999.99’)
from dual
通用函数
这些函数适用于任何数据类型,同时也适用于空值:
NVL (expr1, expr2)
NVL2 (expr1, expr2, expr3)
NULLIF (expr1, expr2)
COALESCE (expr1, expr2, ..., exprn)
NVL 函数
空值转换成一个已知的值:
可以使用的数据类型有日期、字符、数字。
函数的一般形式:
NVL(commission_pct,0)
NVL(hire_date,'01-JAN-97')
NVL(job_id,'No Job Yet')
SELECT last_name, salary, NVL(commission_pct, 0),
(salary*12) + (salary*12*NVL(commission_pct, 0)) AN_SAL
FROM employees;
使用 NVL2 函数
NVL2 (expr1, expr2, expr3) : expr1不为NULL,返回expr2;为NULL,返回expr3。
SELECT last_name, salary, commission_pct,
NVL2(commission_pct,
'SAL+COMM', 'SAL') income
FROM employees WHERE department_id IN (50, 80);
使用 NULLIF 函数
NULLIF (expr1, expr2) : 相等返回NULL,不等返回expr1
SELECT first_name, LENGTH(first_name) "expr1",
last_name, LENGTH(last_name) "expr2",
NULLIF(LENGTH(first_name), LENGTH(last_name)) result
FROM employees;
使用 COALESCE 函数
COALESCE 与 NVL 相比的优点在于 COALESCE 可以同时处理交替的多个值。
如果第一个表达式为空,则返回下一个表达式,对其他的参数进行COALESCE 。
SELECT last_name,
COALESCE(commission_pct, salary, 10) comm
FROM employees
ORDER BY commission_pct;
CASE 表达式
在需要使用 IF-THEN-ELSE 逻辑时:
SELECT last_name, job_id, salary,
CASE job_id WHEN 'IT_PROG' THEN 1.10*salary
WHEN 'ST_CLERK' THEN 1.15*salary
WHEN 'SA_REP' THEN 1.20*salary
ELSE salary END "REVISED_SALARY"
FROM employees;
DECODE 函数
在需要使用 IF-THEN-ELSE 逻辑时:
SELECT last_name, salary,
DECODE (TRUNC(salary/2000, 0),
0, 0.00,
1, 0.09,
2, 0.20,
3, 0.30,
4, 0.40,
5, 0.42,
6, 0.44,
0.45) TAX_RATE
FROM employees
WHERE department_id = 80;
嵌套函数
单行函数可以嵌套。
嵌套函数的执行顺序是由内到外。
F3(F2(F1(col,arg1),arg2),arg3)
F1=>F2=>F3
使用函数对数据进行计算
使用函数修改数据
使用函数控制一组数据的输出格式
使用函数改变日期的显示格式
使用函数改变数据类型
使用 NVL 函数
使用IF-THEN-ELSE 逻辑
多 表 查 询
使用等值和不等值连接在SELECT 语句中查询多个表中的数据。
使用自连接。
使用外连接查询不满足连接条件的数据
从多个表中获取数据
select last_name, department_name
from employees, departments
演示笛卡尔集的错误情况:
select count(employee_id) from employees;
假设输出107行
select count(department_id)from departments;
假设输出27行
select 107*27 from dual;
笛卡尔集
笛卡尔集会在下面条件下产生:
省略连接条件
连接条件无效
所有表中的所有行互相连接
为了避免笛卡尔集, 可以在 WHERE 加入有效的连接条件。
使用连接在多个表中查询数据。
在 WHERE 子句中写入连接条件。
在表中有相同列时,在列名之前加上表名前缀
等值连接
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2;
多个连接条件与 AND 操作符
SELECT employees.employee_id, employees.last_name,
employees.department_id, departments.department_id,
departments.location_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;
区分重复的列名
使用表名前缀在多个表中区分相同的列。
在不同表中具有相同列名的列可以用表的别名加以区分。
表的别名
使用别名可以简化查询。
使用表名前缀可以提高执行效率。
SELECT e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
FROM employees e , departments d
WHERE e.department_id = d.department_id;
非等值连接
SELECT e.last_name, e.salary, j.grade_level
FROM employees e, job_grades j
WHERE e.salary
BETWEEN j.lowest_sal AND j.highest_sal;
外连接
内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行
外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL). 外连接的 WHERE 子句条件类似于内部连接, 但连接条件中没有匹配行的表的列后面要加外连接运算符, 即用圆括号括起来的加号(+).
外连接语法
使用外连接可以查询不满足连接条件的数据。
外连接的符号是 (+)。
右外连接
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column(+) = table2.column;
左外连接
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column = table2.column(+);
自连接
SELECT worker.last_name,
manager.last_name
FROM employees worker, employees manager
WHERE worker.manager_id = manager.employee_id ;
叉 集
使用CROSS JOIN 子句使连接的表产生叉集。
叉集和笛卡尔集是相同的
SELECT last_name, department_name
FROM employees
CROSS JOIN departments ;
自然连接
NATURAL JOIN 子句,会以两个表中具有相同名字的列为条件创建等值连接。
在表中查询满足等值条件的数据。
如果只是列名相同而数据类型不同,则会产生错误。
返回的是,两个表中具有相同名字的列的“且、交集”,而非“或,并集”。即:比如employee类和department类都有department_id和manager_id,返回二者都相同的结果。
自然连接
SELECT department_id, department_name,
location_id, city
FROM departments
NATURAL JOIN locations ;
USING 子句
SELECT e.employee_id, e.last_name, d.location_id
FROM employees e JOIN departments d
USING (department_id) ;
使用ON 子句创建连接(常用)
自然连接中是以具有相同名字的列为连接条件的。
可以使用 ON 子句指定额外的连接条件。
这个连接条件是与其它条件分开的。
ON 子句使语句具有更高的易读性。
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 子句创建多表连接
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;
内连接和外连接(2)
在SQL: 1999中,内连接只返回满足连接条件的数据
两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行,这种连接称为左(或右) 外连接。
两个表在连接过程中除了返回满足连接条件的行以外还返回两个表中不满足条件的行 ,这种连接称为满 外连接。
左外连接
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) ;
右外连接
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;
满外连接
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
FULL OUTER JOIN departments d
ON (e.department_id = d.department_id) ;
分 组 函 数
使用GROUP BY 子句对数据分组。
使用HAVING 子句过滤分组结果集。
组函数类型
AVG
COUNT
MAX
MIN
STDDEV
SUM
AVG(平均值)和 SUM (合计)函数
可以对数值型数据使用AVG 和 SUM 函数。
SELECT AVG(salary), MAX(salary),
MIN(salary), SUM(salary)
FROM employees
WHERE job_id LIKE '%REP%';
MIN(最小值)和 MAX(最大值)函数
可以对任意数据类型的数据使用 MIN 和 MAX 函数
SELECT MIN(hire_date), MAX(hire_date)
FROM employees;
COUNT(计数)函数
COUNT(*) 返回表中记录总数,适用于任意数据类型。
SELECT COUNT(*)
FROM employees
WHERE department_id = 50;
COUNT(expr) 返回expr不为空的记录总数。
SELECT COUNT(commission_pct)
FROM employees
WHERE department_id = 50;
组函数与空值
组函数忽略空值。
SELECT AVG(commission_pct)
FROM employees;
在组函数中使用NVL函数
NVL函数使分组函数无法忽略空值。
SELECT AVG(NVL(commission_pct, 0))
FROM employees;
DISTINCT 关键字
COUNT(DISTINCT expr)返回expr非空且不重复的记录总数
SELECT COUNT(DISTINCT department_id)
FROM employees;
分组数据: GROUP BY 子句语法
可以使用GROUP BY子句将表中的数据分成若干组
在SELECT 列表中所有未包含在组函数中的列都应该包含
在 GROUP BY 子句中。
SELECT department_id, AVG(salary)
FROM employees where department_id <1000
GROUP BY department_id order by department_id desc ;
包含在 GROUP BY 子句中的列不必包含在SELECT 列表中
SELECT AVG(salary)
FROM employees
GROUP BY department_id ;
在GROUP BY子句中包含多个列
SELECT department_id dept_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id ;
非法使用组函数
不能在 WHERE 子句中使用组函数。
可以在 HAVING 子句中使用组函数。
错误:
SELECT department_id, AVG(salary)
FROM employees
WHERE AVG(salary) > 8000
GROUP BY department_id;
过滤分组: HAVING 子句
使用 HAVING 过滤分组:
1. 行已经被分组。
2. 使用了组函数。
3. 满足HAVING 子句中条件的分组将被显示。
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000 ;
嵌套组函数
SELECT MAX(AVG(salary))
FROM employees
GROUP BY department_id;
子 查 询
子查询语法
子查询 (内查询) 在主查询之前一次执行完成。
子查询的结果被主查询(外查询)使用 。
SELECT last_name
FROM employees
WHERE salary >
(SELECT salary
FROM employees
WHERE last_name = 'Abel');
注意事项
子查询要包含在括号内。
将子查询放在比较条件的右侧。
单行操作符对应单行子查询,多行操作符对应多行子查询。
子查询类型
单行子查询 多行子查询
单行子查询
只返回一行。
使用单行比较操作符。
操作符 含义
= Equal to
> Greater than
>= Greater than or equal to
< Less than
<= Less than or equal to
<> Not equal to
返回job_id与141号员工相同,salary比143号员工多的员工
姓名,job_id 和工资
SELECT last_name, job_id, salary
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id = 141)
AND salary >
(SELECT salary
FROM employees
WHERE employee_id = 143);
在子查询中使用组函数
返回公司工资最少的员工的last_name,job_id和salary
SELECT last_name, job_id, salary
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees);
子查询中的 HAVING 子句
首先执行子查询。
向主查询中的HAVING 子句返回结果
SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) >
(SELECT MIN(salary)
FROM employees
WHERE department_id = 50);
非法使用子查询
多行子查询使用单行比较符
子查询中的空值问题
多行子查询
返回多行。
使用多行比较操作符。
操作符 含义
IN 等于列表中的任意一个
ANY 和子查询返回的某一个值比较
ALL 和子查询返回的所有值比较
体会any和all的区别
在多行子查询中使用 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';
在多行子查询中使用 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';