八股文之Oracle

Oracle数据库管理

plsql连接oracle服务器

用户:scott
密码:自己设置的密码
连接的数据库:orcl

默认情况下scott用户只有四张表

emp,bonus,dept,salgrade

八股文之Oracle_第1张图片

八股文之Oracle_第2张图片

用户管理

创建用户账户

查看用户账户

oracle的概要资源

模式

表空间

权限管理

补充SQL初步

DML:Data Manipulation Language 数据操纵语言

DDL:Data Definition Language 数据定义语言

DCL: Data Control Language 数据控制 语言

DDL

DDL用于定义数据库的结构,比如创建,修改或者删除数据库对象,如下操作

  • CREATE TABLE:创建数据库表
  • ALTER TABLE: 更改表结构、添加、删除、修改列长度
  • DROP TABLE:删除表
  • CREATE INDEX:表上建立索引
  • DROP INDEX:删除索引

DML

DML用于查询和修改数据记录,包括如下操作

  • INSERT: 添加数据到数据库
  • UPDATE: 修改数据库中的数据
  • DELETE: 删除数据库中数据
  • SELECT:选择查询数据

其中select是sql语言的基础,最为重要

DCL

DCL用来控制数据库访问,包括如下操作

  • GRANT: 授予访问权限
  • REVOKE:撤销访问权限
  • COMMIT:提交事务处理
  • ROLLBACK:事务处理回退
  • SAVEPOINT:设置保存点
  • LOCK:对数据库特定部分进行锁定

基本SQL语句

基本SELECT语句

语法:SELECT * |{ [DISTINCT] column | expression [alias],...} FROM TABLE;

SELECT 标识 选择那些列

FROM 标识从哪个表中选择

选择全部列

SELECT * FROM EMP;

八股文之Oracle_第3张图片

选择特定的列

SELECT EMPNO , ENAME FROM EMP ;

注意:

SQL语言大小写不敏感

SQL可以写在一行或者多行

关键字不能缩写或者分行

各字句一般要分行写

使用缩进提高语句的可读性

算数运算符

操作符 描述
+
-
*
/
SELECT ENAME , SAL,SAL+100 FROM EMP ;

八股文之Oracle_第4张图片

操作符优先级

  • 乘除优先级高于加减
  • 同一优先级运算符从左往右执行
  • 括号内先运算执行
SELECT ENAME , SAL , SAL*3+300 FROM emp;

八股文之Oracle_第5张图片

使用括号

SELECT ENAME , sal , 10 * (sal + 100) FROM EMP ;

八股文之Oracle_第6张图片

定义空值

/*定义空值*/
SELECT ENAME , SAL ,COMM FROM EMP ;
  • 空值是无效的,未指定的,未知的或者不可预知的值
  • 空值不是空格或者0

空值在数学运算中的使用

-- 包含空值的数学表达式的值都是空值
SELECT ENAME , 10*SAL*COMM FROM EMP ;

八股文之Oracle_第7张图片

列的别名

  • 重命名一个列
  • 便于计算
  • 紧跟列名,也可以在列名和列名之间加入关键字 as,别名使用双引号,以便在别名中包含空格或者特殊字符区分大小写

使用别名

SELECT ENAME NAME,SAL*10 sSL FROM emp;

八股文之Oracle_第8张图片

连接符

  • 把列与列,列与字符连接在一起
  • 使用 '||'表示
  • 可以用来合并列
SELECT empno||ename empnew FROM emp;

八股文之Oracle_第9张图片

字符串

  • 字符串可以是SELECT列表中一个字符,数字,日期
  • 日期和字符只能在单引号中出现
  • 每当返回一行时候,字符串被输出一次
SELECT ename || 'is a ' || sal AS EMPDETAILS FROM emp;

八股文之Oracle_第10张图片

重复行

默认情况,查询返回所有行,包括重复的行

/*重复行*/
SELECT  JOB FROM emp;

/*删除重复行*/
SELECT DISTINCT job FROM emp;

SQL与SQL PLUS

SQL

  1. 一种语言
  2. ANSI标准
  3. 关键字不能缩写
  4. 使用语句空值数据库中的表的定义信息和表中数据

SQL Plus

  1. 一种环境
  2. oracle特性之一
  3. 关键字可以缩写
  4. 命令不能更改数据库中的数据值
  5. 集中运行

可以描述表结构

编辑SQL语句

执行SQL语句

将SQL保存在文件中并且将SQL语句执行结果保存在文件中

在保存的文件中执行语句

将文本文件装入sql plus编辑窗口

显示表结构

desc emp ;
describe emp ;

八股文之Oracle_第11张图片

过滤和排序数据

在查询中过滤行

过滤

  • 使用WHERE子句,将不满足条件的行过滤掉
  • where子句紧随着from子句
SELECT *|{[DISTINCT] column|expression [alias]...} FROM TABLE WHERE conditions
SELECT * FROM emp WHERE sal > 200 ;

字符和日期

  • 字符和日期要包含在单引号中
  • 字符大小写敏感,日期格式敏感
  • 默认的日期格式是DD-MON月-RR
SELECT * FROM emp WHERE ename = 'ALLEN' ;
SELECT * FROM emp  WHERE HIREDATE = '20-2月-1981';

比较运算

操作符 含义
= 等于(不是==)注意:赋值是=》:=
> 大于
>= 大于等于
< 小于
<= 小于等于
<> 不等于(也可以是!=)
SELECT * FROM emp WHERE sal <= 800 ;

其他比较运算

操作符 含义
BETWEEN...AND... 两个值之间
IN 等于值列表中的一个
LIKE 模糊查询
IS NULL 空值

BETWEEN

使用between运算显示一个区间内的值

SELECT * FROM emp WHERE sal BETWEEN 800 AND 1000 ;

IN

使用IN关键字显示列表中值

SELECT * FROM emp WHERE empno IN (7369,7370,7371) ;

Like

  • 使用 LIKE 运算选择类似的值
  • 选择条件可以包含字符或数字:
  • % 代表零个或多个字符(任意个字符)。
  • _ 代表一个字符。
SELECT * FROM emp WHERE empno LIKE '74%';
  • '%‘和’_'同时使用
SELECT * FROM emp WHERE empno LIKE '_4%';
  • 可以使用 ESCAPE 标识符 选择‘%’和 ‘_’ 符号

回避特殊符号的:使用转义符。例如

将[%]转为[%]、[_]转为[_],然后再加上[ESCAPE ‘’]即可

SELECT * FROM emp WHERE empno LIKE '73_%' ESCAPE '\';

NULL

使用 IS NULL 判断空值

SELECT * FROM emp WHERE comm IS NULL ;

逻辑运算

操作符 含义
AND 逻辑并
OR 逻辑或
NOt 逻辑否

AND

要求两边条件都是真

/*AND 逻辑与操作*/
SELECT * FROM emp WHERE sal >=800 AND comm IS NULL ;

OR

要求两边条件一边是真就行

SELECT * FROM emp WHERE sal >= 10000 OR empno LIKE '74%';

NOT

逻辑非操作

SELECT * FROM emp WHERE job NOT IN ('CLERK','MANAGER') ;

查询中排序

优先级

优先级
1 算术运算符
2 连接符
3 比较符
4 is null , like, in
5 between
6 not
7 and
8 or

ORDER BY

  • 使用order by 子句排序
    • asc 升序
    • desc 降序
  • order by子句在select语句的结尾
# 降序
SELECT * FROM emp ORDER BY empno DESC;
# 升序
SELECT * FROM emp ORDER BY empno ;
# 按照别名排序
SELECT empno , sal*20+200 newsal FROM emp ORDER BY newsal DESC ;

单行函数

SQL中不同类型的函数

八股文之Oracle_第12张图片

两种函数

  • 单行函数
  • 多行函数

单行函数

  1. 操作数据对象
  2. 接收参数返回一个结果
  3. 只对一行进行转换
  4. 每行返回一个结果
  5. 可以转换数据类型
  6. 可以嵌套
  7. 参数可以使一列或者一个值
function_name(arg1,arg2,...)
  • 单行函数
    • 字符
    • 数值
    • 日期
    • 转换
    • 通用

字符函数

大小写控制函数

LOWER,UPPER,INITCAP
函数名 函数说明 函数语法
CONCAT 将多个字符串连接成一个字符串 concat(str1, str2,...) 返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。
SUBSTR 字符截取函数 格式1:substr(string str, int a, int b);1、string 需要截取的字符串 2、a 截取字符串的开始位置(注:当a等于0或1时,都是从第一位开始截取) 3、b 要截取的字符串的长度 格式2:substr(string string, int a) ; 1、str 需要截取的字符串 2、a 可以理解为从第a个字符开始截取后面所有的字符串。
LENGTH 表示字符串长度 length(str)
INSTR 字符查找函数 INSTR( string, substring [, start_position [, th_appearance ] ] )string - 要搜索的字符串。字符串可以是CHAR,VARCHAR2,NCHAR,NVARCHAR2,CLOB或NCLOB等类型。 substring - 要在字符串(string)中搜索的子字符串。 子字符串可以是CHAR,VARCHAR2,NCHAR,NVARCHAR2,CLOB或NCLOB等类型。 start_position - 可选的。 在搜索将开始的字符串中的位置。 如果省略,则默认为1。字符串中的第一个位置为1.如果start_position为负数,INSTR函数会从字符串末尾开始计算start_position字符数,然后搜索字符串的开头。 nth_appearance - 可选的。 子串的第n个出现。 如果省略,则默认为1。 返回值:返回一个数字值。 字符串中的第一个位置是1。如果在字符串中找不到substring,那么INSTR函数将返回0。
LPAD 用于往源字符串的左侧填充一些字符 lpad( string1, padded_length, [ pad_string ] )tring1:源字符串padded_length:最终返回的字符串的长度,如果最终返回的字符串的长度比源字符串的小,那么此函数实际上对源串进行截断处理pad_string:用于填充的字符,可以不填,默认为空字符
RPAD 往源字符串的右侧填充一些字符 (字符串string1不能为空). RPAD( string1, padded_length [, pad_string] ) string1:源字符串. padded_length:要返回的字符长度。如果padded_length的值比原字符串的长度小,那么RPAD函数会对字符串进行截取处理。 pad_string:可以为空。用作填充的字符串。如果不填,默认为空格RPAD函数的返回值是字符串。
TRIM 用来去除一个字符串的开头或结尾(或两者)的字符 TRIM([ { { LEADING | TRAILING | BOTH } [ trim_character ] | trim_character } FROM ] trim_source ) leading 开头字符 trailing 结尾字符 both 开头和结尾字符 trim_character 去除的字符 trim_source 修剪源
REPLACE 用另外一个值来替代串中的某个值。 REPLACE ( char, search_string [, replace_string]) 如果没有指定replace_string 变量的值,那么当发现search_string 变量的值时,就将其删除。输入可以为任何字符数据类型——CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB或NCLOB。

举例说明

LOWER:大写字符转换为小写字符

/*大写字符转换小写字符*/
SELECT job FROM emp;
SELECT LOWER(job) FROM emp;

UPPER:小写字符转换大写字符

/*小写字符转换为大写字符*/
SELECT class_name FROM stu_class;
SELECT UPPER(class_name) FROM stu_class;

INITCAP:每个单词的第一个字母大写,其它字母变为小写返回. 单词由空格,控制字符,标点符号等非字母符号限制.

/*INITCAP将字符串首字母变为大写,剩余字符小写*/
SELECT INITCAP('mr pmb') FROM dual;

CONCAT:将多个字符串连接成一个字符串

/*CONCAT:将多个字符串连接成一个字符串*/
SELECT CONCAT('a', 'b', 'c') FROM dual;

/*concat连接多个字符时,需要嵌套*/
SELECT CONCAT(CONCAT('a', 'b'), 'c') FROM dual;

SUBSTR:字符截取函数


/*SUBSTR:字符截取函数*/
SELECT * FROM emp ;
/*第一个数字0或者1时候,都是从第一位开始截取*/
SELECT SUBSTR(ename,0,1) FROM emp ;
SELECT SUBSTR(ename,1,1) FROM emp ;
SELECT ename FROM emp;
/*从第一个字符截取后面所有的字符串(0,1结果都是所有字符串)*/
SELECT SUBSTR(ename,0) FROM emp ;
SELECT SUBSTR(ename,1) FROM emp ;
/*从第二个字符截取后面所有的字符串*/
SELECT SUBSTR(ename,2) FROM emp ;

LENGTH:表示字符串长度


/*LENGTH:表示字符串长度*/
SELECT ename,LENGTH(ename) FROM emp;

INSTR:字符查找函数

/*默认第一次出现 'o'的位置 4*/
SELECT INSTR('ello','o') FROM dual ;

/*也就是说:在"helloworld"的第2(e)号位置开始,查找第二次出现的“l”的位*/
/* instr(源字符串, 目标字符串, 起始位置, 匹配序号)*/
SELECT INSTR('helloworld' , 'l',2,2) FROM dual;

LPAD|RPAD:用于往源字符串的左侧填充一些字符

/*LPAD|RPAD:用于往源字符串的左侧填充一些字符*/
/**
 * 'acb':源字符串
 * 10:填充之后的总字符个数
 * 's': 需要填充的字符
 **/
SELECT LPAD('acb',10,'e') FROM dual ;
-- 返回结果 eeeeeeeacb
SELECT RPAD('acb',10,'e') FROM dual ;
-- 返回结果 acbeeeeeee

TRIM:用来去除一个字符串的开头或结尾(或两者)的字符

/*TRIM:用来去除一个字符串的开头或者结尾*/
/*第一种场景:删除空格*/
/*去除字符串前后空格*/
SELECT ' sd abc ',TRIM(' sd abc ') FROM dual;
/*LTRIM去除指定字符的前面空格*/
SELECT ' sd abc ',LTRIM(' sd abc ') FROM dual;
/*RTRIM去除指定字符后面后空格*/
SELECT ' sd abc ',RTRIM(' sd abc ') FROM dual;

/*第二种场景:去除指定的字符。trim只能去除单个字符,而ltrim和rtrim可以去除多个字符*/
/*表示字符串string2去除前面|后面|前后面(leading|trailing|both)的字符string1,默认去除方式为both*/

/*去除字符串 'abnds' 中 'b'(前面)的 字符*/
SELECT TRIM(LEADING 'b' FROM 'abnds') FROM dual;
/*去除字符串 'nnanbndsn' 中 'n'(两侧)的 字符*/
SELECT TRIM(both 'n' FROM 'nnanbndsn') FROM dual;
/*去除字符串 'abnds' 中 's'(后面)的 字符*/
SELECT TRIM(TRAILING 's' FROM 'abnds') FROM dual;

REPLACE:用另外一个值来替代串中的某个值

/*REPLACE:用另外一个值替代串中的某个值*/
SELECT REPLACE('abcdefg','a','0') FROM dual ;
/*返回结果:0bcdefg*/

SELECT REPLACE('abcdefg','a') FROM dual ;
/*返回结果:bcdefg*/

在select使用字符,数字,日期和转换函数

数字函数

语法:ROUND(number[,decimals])
number 待做截取处理的数值
decimals 指明需保留小数点后面的位数。可选项,忽略它则截去所有的小数部分,并四舍五入。如果为负数则表示从小数点开始左边的位数,相应整数数字用0填充,小数被去掉。需要注意的是,和trunc函数不同,对截取的数字要四舍五入。

作用:截取数字 

案例:
/*截取数字:round*/
SELECT ROUND(123.456,3) FROM dual ; -- 123.456
SELECT ROUND(123.456,2) FROM dual ; -- 123.46
SELECT ROUND(123.456,1) FROM dual ; -- 123.5

语法:TRUNC(date,[fmt])  
date 为必要参数,是输入的一个日期值  fmt 参数可忽略,是日期格式,用以指定的元素格式来截去输入的日期值。忽略它则由最近的日期截去
TRUNC(number[,decimals])  其中:  number 待做截取处理的数值  decimals 指明需保留小数点后面的位数。可选项,忽略它则截去所有的小数部分。 
作用:以指定元素格式截去一部分的日期值或者只是该函数不对指定小数前或后的部分做相应舍入选择处理,而统统截去。

案例:
/*以指定元素格式截去一部分的日期值*/
SELECT TRUNC(SYSDATE, 'yyyy') FROM dual; -- 2022/01/01 返回当年第一天
SELECT TRUNC(SYSDATE, 'mm') FROM dual; -- 2022/01/01 返回当月第一天
SELECT TRUNC(SYSDATE, 'd') FROM dual; -- 2022/01/01 返回当周第一天

SELECT TRUNC(12.345, 2) FROM dual; -- 12.34
SELECT TRUNC(12.345) FROM dual; -- 12.3
SELECT TRUNC(12.345,-1) FROM dual; -- 10 此时 小数点左边指定位数后面的部分截去,均以0记
SELECT TRUNC(12.345,-2) FROM dual; -- 0 此时 小数点左边指定位数后面的部分截去,均以0记

语法:mod(m,n)
MOD返回m除以n的余数,如果n是0,返回m,这个函数以任何数字数据类型或任何非数值型数据类型为参数,可以隐式地转换为数字数据类型。

案例:
/*mod:取余*/
SELECT MOD(12, 6) FROM dual; -- 0
SELECT MOD(12, 7) FROM dual; -- 5
SELECT MOD(-12, 7) FROM dual; -- -5

DUAL 是一个‘伪表’,可以用来测试函数和表达式

日期函数

oracle中的日期型数据实际包含两个值:日期和时间

sysdate函数返回 日期+时间
/*获取当前时间*/
SELECT SYSDATE FROM dual; -- 2022/1/13 20:28:21

日期的数学运算
1、日期上加上或者减去一个数字结果仍然是日期
SELECT sysdate,SYSDATE - 1 FROM dual ;   -- 2022/1/13 20:32:09   2022/1/12 20:32:09

2、两个日期之间相减 为相差的天数
注意:日期不允许加法运算
/*两个日期之间相减 为相差的天数*/
SELECT SYSDATE-hiredate FROM emp;

3、可以使用数字除以24来向日期中加上或者减去天数
/*可以使用数字除以24来向日期中加上或者减去天数*/
SELECT SYSDATE+10/24 FROM DUAL ; -- 往后推迟一天

日期函数
months_between
语法:MONTHS_BETWEEN(DATE1,DATE2)
date1:靠前 date2:靠后

作用:两个日期相差的天数

案例:
SELECT  months_between(SYSDATE,hiredate) FROM emp ;
add_months

add_months
语法:add_months(x,y)或者add_months(times,months)函数
这个函数用于计算在时间x之上加上Y个月后的时间值,要是Y的值为负数的话就是在
这个时间点之间的时间值(这个时间-Y个月)

作用:指定日期添加若干月份

案例:
/*指定日期添加若干月份*/
SELECT hiredate, add_months(hiredate, 1) FROM emp; -- 1980/12/17  1981/1/17

next_day
语法:


作用:指定日期的下一个星期*对应的日期

案例:

执行select sysdate from dual;得到当前日期为:2014/4/30 14:11:33  星期三
select  next_day(sysdate,'星期日') from dual;
得到日期为:2014/5/4 14:12:53
从这个礼拜三到得到礼拜天的日期数

last_day

语法:last_day(date)

作用:指定日期对应月份的最后一天

案例:


/*指定日期的最后一天*/
SELECT last_day(SYSDATE) FROM dual; -- 2022/1/31 20:51:55

转换函数

数据类型转换

源数据类型 目标数据类型
VARCHAR2 OR CHAR NUMBER
VARCHAR2 OR CHAR DATE
NUMBER VARCHAR2
DATE VARCHAR2

TO_CHAR函数对日期的转换

TO_CHAR(date,'format_model')

格式:

  • 必须包含在单引号中并且大小写敏感
  • 可以包含任意的有效的日期格式
  • 日期之间使用都好隔开
SELECT TO_CHAR(SYSDATE, 'yyyy-mm-dd hh:mi:ss') FROM dual; -- 2022-01-13 09:03:51

日期格式的元素

YYYY 2000
YEAR TWO THOUSAND
MM 0
MONTH JULY
MON JUL
DY MON
DAY MONDAY
DD 02

日期格式的元素

  • 时间格式
HH24:MI:SS AM 15:45:32 PM
  • 使用双引号向日期中添加字符
DD "OF"< MONTH/td> 12 OF OCTOBER

to_char对日期的转换

SELECT * FROM EMP WHERE TO_CHAR(HIREDATE,'YYYY-MM-DD')='1980-12-17';

TO_DATE对字符的转换

to_date(char,'format_model');

to_date('2022年01月13日21:29:00','yyyy"年"mm"月"dd"日"hh:mi:ss') from dual ;

SELECT to_date('2022年01月13日 1:29:33','yyyy"年"mm"月"dd"日"hh:mi:ss') from dual ;     2022/1/13 1:29:33

TO_DATE对数字的转换

下面是在TO_CHAR 函数中经常使用的几种格式

9 数字
0
$ 美元符
L 本地货币符号
. 小数点
, 千位符
DAY MONDAY
DD 02

案例说明

SELECT to_char(sal, '$99,999.00') FROM emp; --   $1,250.00

通用函数

NVL(exp1,expr2)

nvl2(expr1,expr2,expr3)

nullif(expr1,expr2)

coalesce(expr1,expr2,…)

-- 通用函数
/**
 * NVL:将空值转换成一个已知的值
 * 如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值。
 * NVL(EXPR1,EXPR2)
 **/
SELECT NVL('第一个参数不为空的值v1','第一个参数空的时候值v2') FROM DUAL;

/**
 * NVL2(EXPR1,EXPR2,EXPR3)
 * 如果该函数的第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第三个参数的值
 **/                 
 SELECT NVL2('',1,2) FROM DUAL; -- 2
 
/**
 * NULLIF(EXPR1,EXPR2)
 * 作用:如果expr1和expr2相等返回null,否则返回第一个值
 **/                                
 SELECT NULLIF(1,2) FROM DUAL;  -- 1   
 
/**
 * COALESCE(EXPR1,V1,...VN)
 * EXPR1:为待检测的表达式,而其后的参数个数不定。
 * 返回值:包括EXPR1在内的所有参数中的第一个非空表达式
 **/                                                          
 
 SELECT COALESCE(NULL,3,4,5) FROM DUAL;

使用条件表达式

  • 在SQL语句中使用IF-THEN-ELSE逻辑
  • 使用两种方法
    • CASE表达式
    • DECODE函数

简单case表达式

-- 简单case表达式
SELECT job,
       CASE JOB
         WHEN 'CLERK' THEN
          'clerk'
         WHEN 'SALESMAN' THEN
          'salesman'
         ELSE
          '其他'
       END
  FROM EMP;

搜索case表达式

-- 搜索case表达式
SELECT JOB, CASE
         WHEN JOB = 'CLERK' THEN
          '职员'
         WHEN JOB = 'SALESMAN' THEN
          '推销员'
         ELSE
          '马会计'
       END
  FROM emp;

注意事项

  • 统一各分支返回的数据类型

虽然这一点无需多言,但这里还是要强调一下:一定要注意 CASE 表达式里各个分支返回的数据类型是否一致。某个分支返回字符型,而其他分支返回数值型的写法是不正确的。

  • 不要忘了写 END

使用 CASE 表达式的时候,最容易出现的语法错误是忘记写 END 。虽然忘记写时程序会返回比较容易理解的错误消息,不算多么致命的错误。但是,感觉自己写得没问题,而执行时却出错的情况大多是由这个原因引起的,所以请一定注意一下。

  • 养成写 ELSE 子句的习惯

与 END 不同,ELSE 子句是可选的,不写也不会出错。不写 ELSE 子句时,CASE 表达式的执行结果是 NULL 。但是不写可能会造成"语法没有错误,结果却不对"这种不易追查原因的麻烦,所以最好明确地写上 ELSE 子句(即便是在结果可以为 NULL 的情况下)。养成这样的习惯后,我们从代码上就可以清楚地看到这种条件下会生成 NULL,而且将来代码有修改时也能减少失误

decode

-- decode函数的两种形式
-- 第一种格式
-- DECODE(EXPR,V1,R1,V2,R2...VN,RN,DEFAULT)
/**
 * IF 条件=V1 THEN R1
 * ELSIF 条件=v2 THEN R2
 * ELSIF 条件=VN THEN RN
 * ELSE RD(缺省值)
 * END IF
 **/
-- 当JOB='CLERK',返回值1 
-- 当JOB='SALESMAN',返回值2
-- 当JOB='MANAGER',返回值3
SELECT EMPNO,
       ENAME,
       JOB,
       DECODE(JOB, 'CLERK', 1, 'SALESMAN', 2, 'MANAGER', 3) NEW_JOB
  FROM EMP;

-- 判断表中sal大小根据大小划分不同范围
SELECT * FROM emp;

SELECT DECODE(SIGN(), 1,) FROM emp;
-- 第二种格式
-- DECODE(字段或者字段运算,V1,V2,V3)
-- 这个函数运行的结果是,当字段或者字段的运算的值等于值1时,该函数返回值2,否则返回值3
-- 当然v1,v2,v3也可以是表达式,这个函数使得SQL语句简单了许多
-- 比较大小
-- SIGN(100-90)表达式值等于-1时候,返回100,否则90
SELECT DECODE(SIGN(100 - 90), -1, 100, 90) FROM DUAL;

-- 使用表达式来搜索字符串
SELECT DECODE(INSTR('ACM', 'C'), 0, '不含有C', '含有C') FROM DUAL; -- 含有C

-- 实现行列转换
-- decode相当于:case when then else end语句
SELECT DECODE(JOB, 'CLERK', ENAME, 0) ENAME_1,
       DECODE(JOB, 'SALESMAN', ENAME, 0) ENAME_2,
       DECODE(JOB, 'MANAGER', ENAME, 0) ENAME_3
  FROM emp;

SELECT * FROM emp;

-- 创建表,插入数据,查询
CREATE TABLE t_decode(id INTEGER, NAME VARCHAR2(10));

-- 插入数据
INSERT INTO t_decode VALUES (1, 'a');
INSERT INTO t_decode VALUES (2, 'b');
INSERT INTO t_decode VALUES (3, 'c');
INSERT INTO t_decode VALUES (4, 'a');

SELECT * FROM T_DECODE;

SELECT decode(NAME, 'a', id, 0) id_1,
       decode(NAME, 'b', id, 0) id_2,
       decode(NAME, 'c', id, 0) id_3
  FROM t_decode;

多表查询

使用等值和不等值连接在SELECT语句中查询多个表中的数据

使用自连接

使用外连接查询不满足连接条件的数据

使用等值和不等值连接在SELECT语句中查询多个表中的数据

从多个表中获取数据

八股文之Oracle_第13张图片

内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。

区分重复的列名

  • 使用表名前缀在多个表中区分相同列
  • 不同表中具有相同列名的列可以用表别名加以区分
SELECT * FROM EMP E, DEPT D WHERE EMP.DEPTNO = DEPT.DEPTNO;

八股文之Oracle_第14张图片

  • 使用别名可以简化查询
  • 使用表名前缀可以提高执行效率

连接多个表

连接n个表,至少需要n-1个连接条件

SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S, SCORE S1, STU_CLASS SC
 WHERE S.STU_ID = S1.STU_ID
   AND S1.CLASS_ID = SC.CLASS_ID;

八股文之Oracle_第15张图片

等值连接

等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复属性。

-- ,形式 and
SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S, SCORE S1, STU_CLASS SC
 WHERE S.STU_ID = S1.STU_ID
   AND S1.CLASS_ID = SC.CLASS_ID;
-- INNER JOIN ON   
SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S
 INNER JOIN SCORE S1
    ON S.STU_ID = S1.STU_ID
 INNER JOIN STU_CLASS SC
    ON S1.CLASS_ID = SC.CLASS_ID;

image-20220115211726051

非等值连接

不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的 列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。

内连接和外连接

内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行

外连接:两个表在连接过程中除了返回满足连接条件的行之外还需要返回左表或者右表不满足条件的行,这种连接叫做左(右)外连接,没有匹配的行时候,结果表中响应的列为null,外连接的where子句条件类似于内部连接,但是连接条件中没有匹配行的表的列后面需要加上外连接运算符,即 用圆括号括起来的加号。

使用外连接查询不满足连接条件的数据

对应SQL:LEFT/RIGHT/FULL OUTER JOIN。 通常省略OUTER关键字, 写成:LEFT/RIGHT/FULL JOIN。

在左连接和右连接时都会以一张A表为基础表,该表的内容会全部显示,然后加上A表和B表匹配的内容。 如果A表的数据在B表中没有记录。 那么在相关联的结果集行中列显示为空值(NULL)

对于外连接, 也可以使用“(+) ”来表示。 关于使用(+)的一些注意事项

该操作符只能出现在WHERE子句中,并且不能和OURTER JOIN语法同时使用

使用该操作符执行外连接时候,如果WHERE子句包含多个条件,必须在所有条件都包含+操作符

操作符只适用于列,不能用在表达式

操作符不能和OR,IN一起使用

操作符只能用于左外连接和右外连接,不能用于全外连接

左外连接

LEFT JOIN是以左表的记录为基础的,示例中t_A可以看成左表,t_B可以看成右表,它的结果集是t_A表中的全部数据,再加上t_A表和t_B表匹配后的数据。换句话说,左表(t_A)的记录将会全部表示出来,而右表(t_B)只会显示符合搜索条件的记录。t_B表记录不足的地方均为NULL。

语法

-- + 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1,T2 WHERE T1.COLUMN=T2.COLUN(+);

-- LEFT OUTER JOIN 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1 LEFT OUTER JOIN T2 ON T1.COLUMN = T2.COLUMN;

举例说明

-- 返回右表不满足条件的数据
-- 方式1 +
SELECT * FROM STUDENT S1, SCORE S2 WHERE S1.STU_ID = S2.STU_ID(+);

-- 方式2 LEFT OUTER JOIN                      
SELECT *
  FROM STUDENT S1
 LEFT OUTER JOIN SCORE S2
    ON S1.STU_ID = S2.STU_ID;

八股文之Oracle_第16张图片

右外连接

和LEFT JOIN的结果刚好相反,是以右表(SCORE)为基础的。它的结果集是STUDENT表所有记录,再加上SCORE和STUDENT匹配后的数据。STUDENT表记录不足的地方均为NULL。

语法

-- + 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1,T2 WHERE T1.COLUMN(+)=T2.COLUN;

-- LEFT OUTER JOIN 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1 RIGHT OUTER JOIN T2 ON T1.COLUMN = T2.COLUMN;

用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配表。如果加号写在左表,右表就是全部显示,所以是右连接

举例说明

-- 方式1 +
SELECT * FROM STUDENT S1, SCORE S2 WHERE S1.STU_ID(+)= S2.STU_ID;

-- 方式2 RIGHT OUTER JOIN                      
SELECT *
  FROM STUDENT S1
RIGHT OUTER JOIN SCORE S2
    ON S1.STU_ID = S2.STU_ID;

全外连接(FULL OUTER JOIN/FULL JOIN)

完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值

-- FULL JOIN
SELECT * FROM STUDENT S1 FULL JOIN SCORE S2 ON S1.STU_ID = S2.STU_ID; 
-- FULL OUTER JOIN
SELECT * FROM STUDENT S1 FULL OUTER JOIN SCORE S2 ON S1.STU_ID = S2.STU_ID; 

八股文之Oracle_第17张图片

自然连接(NATURAL)

自然连接时在两张表中寻找那些数据类型 和列名都相等的字段,然后自动地将他们连接起来

自然连接,自动匹配同名的列,虽然很方便,不用指定匹配的列

但也有缺点,虽然可以指定查询结果包括哪些列,但不能人为地指定哪些列被匹配,而内连接就可以自由指定

分组函数

通过本次学习,可以知道

  • 了解组函数
  • 描述组函数的用途
  • 使用GROUP BY 子句对数据分组
  • 使用HAVING子句过滤分组结果集

什么是分组函数

分组函数作用于一组数据,并对一组数据返回一个值

组函数类型

AVG 平均值
COUNT 计数
MAX 最大值
MIN 最小值
SUM 求和

AVG()平均值和SUM()求和函数

  • 可以对数值型数据使用SUM和SUM函数
  • AVG组函数忽略空值
SELECT AVG(SAL) FROM EMP;  -- 平均值
SELECT SUM(SAL) FROM EMP;  -- 求和

MIN(最小值)和 MAX(最大值)函数

  • 可以对任意数据类型的数据使用 MIN 和 MAX 函数
-- MAX,MIN
SELECT MAX(SAL)  MAX_VALUE,MIN(SAL) MIN_VALUE FROM EMP;

COUNT(计数)函数

  • 返回记录表中符合条件的记录总数,适用于任意数据类型
  • 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值
  • 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值
-- COUNT(*)
SELECT COUNT(*) FROM EMP WHERE DEPTNO = 20 ;

-- 为空时候
SELECT COUNT(COMM) FROM emp;

八股文之Oracle_第18张图片

组函数与空值

SELECT SUM(COMM),COUNT(*),AVG(COMM) FROM EMP;

原始表中有14条数据,结果看见avg(comm)只对非NULL的数据进行平均操作,那是因为oracle的组函数不会将null的数据进行忽略,如果需要实现对14个人取平均怎么办?

只需要对comm进行nvl操作,将null转换为0,那么组函数就能将这些null数据纳入统计范围了

在组函数中使用NVL函数

  • NVL函数使分组函数无法忽略空值
SELECT SUM(COMM),COUNT(*),AVG(NVL(COMM,0)) FROM EMP;

八股文之Oracle_第19张图片

DISTINCT 关键字

  • COUNT(DISTINCT expr)返回expr非空且不重复的记录总数
SELECT DISTINCT(DEPTNO) FROM EMP;

分组数据: GROUP BY 子句语法

  • 可以使用GROUP BY子句将表中的数据分成若干组
  • 使用聚合函数中用group by来分组数据时特别说明了select 列表项中不存在的列可以出现在group by的列表项中,但反过来就不行了,在select列表项中出现的列必须全部出现在group by后面(聚合函数除外)

WHERE一定放在FROM后面

-- WHERE一定放在FROM后面
SELECT * FROM emp WHERE deptno IN(10,20,30);

在SELECT列表中所有未包含在组函数中的列都应该包含在GROUP BY 子句中

-- 错误示范
SELECT ENAME, DEPTNO FROM EMP GROUP BY DEPTNO;
-- 正确示范
SELECT  DEPTNO ,COUNT(DEPTNO)FROM EMP GROUP BY DEPTNO;

八股文之Oracle_第20张图片

包含在 GROUP BY 子句中的列不必包含在SELECT 列表中

-- 包含在 GROUP BY 子句中的列不必包含在SELECT 列表中
SELECT AVG(sal) FROM emp GROUP BY deptno;

使用多个列分组

-- 多个列分组
SELECT deptno,empno,AVG(sal) FROM emp GROUP BY deptno,empno;

可以在 HAVING 子句中使用组函数

-- 可以在 HAVING 子句中使用组函数
SELECT deptno,AVG(sal) FROM emp HAVING AVG(sal) > 500 GROUP BY deptno;

不能在 WHERE 子句中使用组函数

可以在order by 子句中使用组函数

-- 可以在order by 子句中使用组函数
SELECT deptno, AVG(sal)
  FROM emp
HAVING AVG(sal) > 500
 GROUP BY deptno
 ORDER BY AVG(sal);

非法使用组函数

-- 非法使用组函数
-- 所有包含于SELECT 列表中,而未包含于组函数中的列都必须包含于 GROUP BY 子句中
-- 错误提示:ORA-00937:不是单组分组函数 ,group by 缺少列
SELECT deptno, COUNT(deptno) FROM emp;
-- 不能在 WHERE 子句中使用组函数
-- 错误提示:ORA-00934:此处不允许使用分组函数
SELECT deptno, AVG(sal) FROM emp WHERE AVG(sal) > 500 GROUP BY deptno;
-- 可以在 HAVING 子句中使用组函数
SELECT deptno, AVG(sal)
  FROM emp
HAVING AVG(sal) > 500
 GROUP BY deptno;

过滤分组:HAVING 子句

使用HAVING过滤分组

  • 行已经被分组
  • 使用了组函数
  • 满足HAVING子句条件的分组将被显示
SELECT COLUMN,GROUP_FUNCTION
FROM TABLE
WHERE CONDITION
GROUP BY GROUP_BY_EXPRESSION
HAVING GROUP_CONDITION
ORDER BY COLUMN;

简单使用HAVING

-- 简单使用HAVING
SELECT DEPTNO,AVG(SAL) FROM EMP GROUP BY DEPTNO HAVING MAX(SAL) > 500 ;

嵌套组函数

-- 求出平均工资最高的部门编号,部门名称,部门平均工资
SELECT d.deptno, d.dname, e.sal
  FROM (SELECT AVG(sal) sal, deptno
          FROM emp e
         GROUP BY deptno
        HAVING AVG(sal) = (SELECT MAX(AVG(sal)) FROM emp GROUP BY deptno)) e
  LEFT JOIN dept d
    ON e.deptno = d.deptno;


子查询

目标

  • 描述子查询可以寄解决的问题
  • 定义子查询
  • 列出子查询的类型
  • 书写单行子查询和多行子查询

使用子查询解决的问题

谁的工资比BLAKE高

子查询基本语法

  • 子查询(内查询)在主查询之前一次执行完成
  • 子查询的结果被主查询(外查询)使用
SELECT SELECT_LIST FROM TABLE WHERE EXPR OPERATOR(SELECT SELECT_LIST FROM TABLE)

-- 谁的工资比BLAKE高
SELECT ename,sal
  FROM emp
 WHERE sal >= (SELECT sal FROM emp WHERE ename = 'BLAKE');

注意事项

子查询要包含在括号内

将子查询放在比较条件的右侧

单行操作符对应单行子查询,多行操作符对饮多行子查询

子查询类型

单行子查询:从子查询中返回一行结果的查询

多行子查询:从子查询中返回多行结果的查询

单行子查询

  • 只返回一行
  • 使用单行比较操作符
操作符 含义
= Equal to
> Greater than
>= Greater than or equal to
< Less than
<> Not equal to
-- 子查询解决的问题
-- 谁的工资比BLAKE高
SELECT * FROM EMP;

-- 子查询的基本语法
SELECT SELECT_LIST
  FROM TABLE
 WHERE EXPR OPERATOR (SELECT SELECT_LIST FROM TABLE);

-- 基本使用
SELECT ENAME, SAL
  FROM EMP
 WHERE SAL >= (SELECT SAL FROM EMP WHERE ENAME = 'BLAKE');

-- 执行单行子查询
-- 返回JOB和7654号员工相同,SAL比7654号员工多的员工姓名,JOB和工资
SELECT ename, job, sal
  FROM emp
 WHERE job = (SELECT job FROM emp WHERE empno = 7369)
   AND sal > (SELECT sal FROM emp WHERE empno = 7369);
-- 子查询中使用组函数
-- 返回公司工资最少的员工的name,job和sal
SELECT ename, job, sal FROM emp WHERE sal = (SELECT MIN(sal) FROM emp);
-- 子查询中使用HAVING
-- 首先执行子查询
-- 向主查询中HAVING子句中返回结果
-- 题目:查询最低工资大于10号部门最低工资的deptno和其最低工资
SELECT deptno, MIN(sal)
  FROM emp
 GROUP BY deptno
HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 20);

-- 非法使用子查询
SELECT deptno, ename
  FROM emp
 WHERE sal = (SELECT MIN(sal) FROM emp GROUP BY deptno);
/**
 *  ERROR at line 4:
 * ORA-01427: single-row subquery returns more than
 * one row
 **/

-- 子查询中空值问题
SELECT deptno, MIN(sal)
  FROM emp
 GROUP BY deptno
HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 10);

多行子查询

  • 返回多行
  • 使用多行比较操作符
操作符 含义
IN 等于列表中任意一个
ANY 和子查询返回的某一个值比较
ALL 和子查询返回的所有值比较
-- 查询工资低于任何一个“CLERK”岗位的工资的雇员信息
SELECT SAL FROM EMP WHERE JOB = 'CLERK';

SELECT MAX(SAL) FROM EMP WHERE JOB = 'CLERK';

SELECT *
  FROM EMP
 WHERE SAL < (SELECT MAX(SAL) FROM EMP WHERE JOB = 'CLERK');

SELECT * FROM EMP;
SELECT *
  FROM EMP
 WHERE SAL < ANY (SELECT SAL FROM EMP WHERE JOB = 'CLERK');

--查询工资比所有的'SALESMAN'职位都高的雇员的编号,名字和工资
--[1]'SALESMAN'工资都是多少?
SELECT SAL FROM EMP WHERE JOB = 'SALESMAN';

SELECT EMPNO, ENAME, SAL
  FROM EMP
 WHERE SAL > ALL (SELECT SAL FROM EMP WHERE JOB = 'SALESMAN');

--查询部门20中的职务同部门10的雇员一样的雇员信息.
--[2]部门10是什么职务
SELECT JOB FROM EMP WHERE DEPTNO = 10;

SELECT *
  FROM EMP
 WHERE JOB IN (SELECT JOB FROM EMP WHERE DEPTNO = 10)
   AND DEPTNO = 20;

创建和管理表

该章节学习之后,我们可以

  • 了解主要的数据库对象
  • 创建表
  • 描述各种数据类型
  • 修改表的定义
  • 删除,重命名和清空表

常见的数据库对象

对象 描述
基本的数据存储集合,由行和列组成
视图 从表中抽出的逻辑上相关的数据集合
序列 提供有规律的数值
索引 提高查询效率
同义词 给对象起别名

命名规则

表名和列名:

  • 必须以字母开头
  • 必须在 1–30 个字符之间
  • 必须只能包含 A–Z, a–z, 0–9, _, $, 和 #
  • 必须不能和用户定义的其他对象重名
  • 必须不能是Oracle 的保留字

创建表

-- 创建表
CREATE TABLE ddept(deptno NUMBER(23), dname VARCHAR2(22), loc VARCHAR2(22));

SELECT * FROM ddept;

数据类型

数据类型 描述
varchar2(size) 可变长字符数据
char(size) 定长字符数据
number 可变长数值数据
date 日期类型
long 可变长字符数据
clob 字符数据
blob 二进制数据
rowid 行地址

使用子查询创建表

-- 语句:
CREATE TABLE tablename[(column1,column2,column3.....] AS subquery;

例子:

1.create table tabletest as select * from emp where 1=2;

这句话后面的where条件为假,表示只复制表的结构,而不复制数据,当where表后面的条件为真的时候,表示结构和表都复制过去。
2.create table emp20 as select * from emp where deptno=20;
这句话表示会将表的结构以及部门为20号的员工的信息复制过来。

Alter Table语句

  1. 追加新的列
  2. 修改现有的列
  3. 为新追加的列定义默认值
  4. 删除一个列
  5. 重命名表的一个列名

修改列

alter table dept modify (last_name varchar2(30));
alter table dept modify (last_name varchar2(30) default '来来来');
-- 对默认值的修改只影响今后对表的修改

追加列

alter table dept add (job_id varchar2(10));

删除列

alter table dept drop column job_id;

重命名列

alter table dept rename column job_id to id ;

删除表

  • 数据和结构都被删除
  • 所有正在运行的相关事务被提交
  • 所有相关索引被删除
  • DROP TABLE 语句不能回滚

总结

八股文之Oracle_第21张图片

sql中关于if判断使用

case end语法

SELECT
	CASE
		WHEN math>100 THEN '优'
		WHEN math>90 THEN '良'
		WHEN math>80 THEN '中'
		WHEN math>70 THEN '及格'
		WHEN math IS NULL THEN '缺考'
		ELSE '不及格'
	END
FROM
	Person;

SELECT COUNT(order_num),
       SUM(CASE
             WHEN item_price > 3 THEN
              1
             ELSE
              0
           END)
  FROM orderitems;
/* DECODE方法*/
SELECT COUNT(order_num), SUM(DECODE(1, item_price, 0)) FROM orderitems;

-- 判断字符串
-- 说明:字段empno如果是7014返回1,如果是7015返回2
SELECT empno, ename, COUNT(DECODE(empno, '7014', 1, '7015', 2)) FROM emp;

-- 函数分段
--(负无穷,2)
-- [2,4)
-- [4,+无穷)
SELECT * FROM t_decode;
SELECT ID,
       NAME,
       DECODE(SIGN(ID - 4),
              1,
              'high id',
              0,
              'high id',
              '-1',
              DECODE(SIGN(ID - 2), 1, 'mid id', 0, 'mid id', -1, 'low id'))
  FROM t_decode
   FOR UPDATE;

-- 比较大小
SELECT DECODE(SIGN(100 - 90), -1, 100, 90) FROM dual;

-- 表达式搜索字符串
SELECT ID, NAME, DECODE(INSTR(NAME, 'a'), 0, '不含有a', '含有a')
  FROM t_decode;

-- 行列转换
SELECT DECODE(JOB, 'CLERK', ENAME, 0) ENAME_1,
       DECODE(JOB, 'SALESMAN', ENAME, 0) ENAME_2,
       DECODE(JOB, 'MANAGER', ENAME, 0) ENAME_3
  FROM emp;

你可能感兴趣的:(面试题,oracle,数据库,sql)