Oracle 的 SQL 语句分类:
DQL(Data Query Language):数据库查询语言,关键字:select
DML(Data Manipulation Language):数据操纵语言,关键字:Insert、delete、update
DDL(Data Definition Language):数据库模式定义语言,关键字:create、alter、drop
DCL(Data Control Language):数据库控制语言 ,关键字:grant,给用户赋权限;revoke,收回用户的权限
TCL(Transaction Control Language):数据库事务操控语句,关键字:commit、rollback
1. SELECT
2. DISTINCT <select_list>
3. FROM <left_table>
4. <join_type> JOIN <right_table>
5. ON <join_condition>
6. WHERE <where_condition>
7. GROUP BY <group_by_list>
8. HAVING <having_condition>
9. ORDER BY <order_by_condition>
10.LIMIT <limit_number>
FROM
<表名> # 选取表,将多个表数据通过笛卡尔积变成一个表。
ON
<筛选条件> # 对笛卡尔积的虚表进行筛选
JOIN
# 指定join,用于添加数据到on之后的虚表中,例如left join会将左表的剩余数据添加到虚表中
WHERE
# 对上述虚表进行筛选
GROUP BY
<分组条件> # 分组
# 用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的
HAVING
<分组筛选> # 对分组后的结果进行聚合筛选
SELECT
<返回数据列表> # 返回的单列必须在group by子句中,聚合函数除外
DISTINCT
# 数据除重
ORDER BY
<排序条件> # 排序
LIMIT
<行数限制>
CREATE TABLE table_name AS SELECT * FROM old_table_name;
## 1.2 只复制表结构
```sql
CREATE TABLE table_name AS SELECT * FROM old_table_name WHERE 1=2;
INSERT INTO table_name select * from old_table_name;
Insert into table_name(column1,column2...) select column1,column2 from old_table_name;
row_number(): 连续排序,不会出现重复值
:1 2 3 4 5
rank(): 跳跃排序,如果有两个 2 时,接下来就是 4
:1 2 2 4 5
dense_rank(): 连续排序,如果有两个 2 时,接下来仍然是 3
:1 2 2 3 4 5
select empno, ename, job, hiredate, sal, deptno, rank() over(partition by deptno order by sal desc) r from emp;
select empno, ename, job, hiredate, sal, deptno, dense_rank() over(partition by deptno order by sal desc) r from emp;
可查询每个部门下的最高、最低工资
select ename 姓名, job 职业, hiredate 入职日期, deptno 部门,
min(sal) over(partition by deptno) 部门最低工资,
max(sal) over(partition by deptno) 部门最高工资
from emp order by deptno, sal;
select ename 姓名, job 职业, hiredate 入职日期, deptno 部门,
nvl(sal - min(sal) over(partition by deptno), 0) 部门最低工资差额,
nvl(max(sal) over(partition by deptno) - sal, 0) 部门最高工资差额
from emp order by deptno, sal;
lead(列名,n,m): 当前记录后面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录后面第一行的记录<列名>的值,没有则默认值为null。
lag(列名,n,m): 当前记录前面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录前面第一行的记录<列名>的值,没有则默认值为null。
select ename 姓名, job 职业, sal 工资, deptno 部门,
lead(sal, 1, 0) over(partition by deptno order by sal) 比自己工资高的部门前一个,
lag(sal, 1, 0) over(partition by deptno order by sal) 比自己工资低的部门后一个,
nvl(lead(sal) over(partition by deptno order by sal) - sal, 0) 比自己工资高的部门前一个差额,
nvl(sal - lag(sal) over(partition by deptno order by sal), 0) 比自己工资高的部门后一个差额
from emp;
常用语法
select ename 姓名, job 职业, sal 工资, deptno 部门,
first_value(sal) over(partition by deptno) first_sal,
last_value(sal) over(partition by deptno) last_sal,
sum(sal) over(partition by deptno) 部门总工资,
avg(sal) over(partition by deptno) 部门平均工资,
count(1) over(partition by deptno) 部门总数,
row_number() over(partition by deptno order by sal) 序号
from emp;
select * ,first_value(s_id) over (partition by c_id order by s_score)first_show from score;
select * ,last_value(s_id) over (partition by c_id order by s_score)first_show from score;
CONNECT BY PRIOR child_id = parent_id
SELECT *
FROM table_name
START WITH child_name = 'XXX'
CONNECT BY PRIOR child_id = parent_id;
CONNECT BY PRIOR parent_id = child_id
SELECT *
FROM table_name
START WITH child_name = 'XXX'
CONNECT BY PRIOR parent_id = child_id;
NVL(expr1, expr2)
:
NULL
。如果expr1
是null
,则返回expr2
,如果expr1
不是null
,则返回expr1
。NVL2(expr1, expr2, expr3)
expr1
不是null
,则返回expr2
,如果expr1
是null
,则返回expr3
。NULLIF(expr1, expr2)
expr1
和expr2
,如果二者相等,则返回NULL
,否则返回expr1
。COALESCE(expr1 [ , expr2 ] [, ... ])
NOT NULL
表达式的结果。union操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。
select ename,sal,job from emp where sal>3500
union
select ename,sal,job from emp where job='MANAGER';
union all操作符与union相似,但是它不会取消重复行,而且不会排序。
select ename,sal,job from emp where sal>3500
union all
select ename,sal,job from emp where job='MANAGER';
intersect操作符用于取得两个结果集的交集。
select ename,sal,job from emp where sal>3500
intersect
select ename,sal,job from emp where job='MANAGER';
minus操作符用于取得两个结果集的差集,它只会显示存在第一个集合中,而不存在第二个集合中的数据。
select ename,sal,job from emp where sal>3500
minus
select ename,sal,job from emp where job='MANAGER';
select * from emp where rownum<=6 and rownum >=4;
查询之后没有发现任何结果,为什么呢?
原因很简单,Oracle机制就是这样的:ROWNUM是oracle系统顺序分配给查询返回的结果的行的编号,返回的第一行分配的是1,不符合>=4的条件,所以第一行被去掉,之前的第二行变为新的第一行(即这个行号不是写死的,可以理解为是动态的)
,如此下去,一直到最后一行,条件始终没法满足,所以就一条数据也查不出来。
因此,解决方法也就很明显了,我们只要将行号查询出来生成一个结果集,然后再从这个结果集中,选择行号大于我们设定的那个值就可以了。
select * from (select emp.*,rownum rn from emp where rownum<=6) e where e.rn>=4;
#start:从第几条开始
#count:取几条数据
select * from 表名 where 条件 limit start,count;
select * from emp,dept;
以上语句存在笛卡尔积,查询数据结果条数为(emp条数 * dept条数)
A.多表查询的条件至少不能少于(表的个数-1)
B.一般采用关联字段进行判断
select ename,sal,dname from emp e,dept d where e.deptno=d.deptno;
语法:
select 列名1,.. from 表1 [inner] join 表2 on 条件 where 条件;
注意:on后面是连接条件
select * from emp e inner join dept d on e.deptno=d.deptno;
select * from emp e inner join dept d on e.deptno>d.deptno;
外连接分为三种:左外连接
、右外连接
和完全外连接
。
返回包括左表中的所有记录和右表中联结字段相等的记录。
语法:
select 列名1,列名2,.. from 表1 left [outer] join 表2 on 条件;
select stu.id,name,grade from stu left join exam on stu.id=exam.id;
返回包括右表中的所有记录和左表中联结字段相等的记录。
语法:
select 列名1,列名2,.. from 表1 right [outer] join 表2 on 条件;
select stu.id,name,grade from stu right join exam on stu.id=exam.id;
返回查询结果等于左外连接和右外连接的和。
select stu.id,name,grade from stu full join exam on stu.id=exam.id;
chr(n)
:ASCII码值转字符
select chr(65)||chr(66)||chr(67),chr(54678) from dual;
ascii(char)
:字符转码值
select ascii('叶'),ascii('asd') from dual;
UPPER(char)
:字符转成大写
LOWER(char)
:字符转成小写
INITCAP(char)
:字符首字母转成大写
CONCAT(str1, str2)
:连接字符串
SUBSTR(str,m,n)
: 截取字符串
substr('hello'1,3)--> hel;
substr('hello',0,3)--> hel, 两个结果一样;
substr('hello',-1,1)--> o
LENGTH(char)
: 返回字符串长度
INSTR(char1, char2, n,m)
:该函数用于取得子串在字符串中的位置,char1用于指定源字符串,char2用于指定子串,n用于指定起始搜索位置(默认值1),m用于指定子串的第m次出现的次数(默认1)。
instr('hello oracle', 'oracle')=7;
instr('hello oracle hello oracle', 'oracle', 1, 2)=20。
LPAD(char1, n, char2)
:该函数用于在字符串的左端填充字符,char1用于指定源字符串,char2用于指定被填充的字符,n用于指定填充后的char1的总长度。
lpad('hello',10,'#')--> #####hello。
RPAD(char1, n ,char2)
:该函数用于在字符串的右端填充字符.
rpad('hello',10,'#')--> hello#####。
REPLACE(char, old, new)
:该函数用于替换字符串的子串内容。
replace('hello oracle', 'oracle', 'world'),结果为:hello world。
TRIM、LTRIM、RTRIM
TRIM
去除指定字符的前后空格LTRIM
去除指定字符的前面空格RTRIM
去除指定字符后面后空格SELECT TRIM(' dd df ') FROM dual;
--------
'dd df'
SELECT LTRIM(' dd df ') FROM dual;
--------
'dd df '
SELECT RTRIM(' dd df ') FROM dual;
--------
' dd df'
TRIM
只能去除单个字符,而LTRIM
和RTRIM
可以去除多个字符。
TRIM(leading|trailing|both string1 FROM string2)
string2
去除左边|右边|左右边(leading|trailing|both)
的字符string1
,默认去除方式为both
LTRIM(string1,string2)
表示字符串string1
去除左边开始与string2
字符集匹配的,把string2
看成一个池子。RTRIM(string1,string2)
表示字符串string1
去除右边开始与string2
字符集匹配的,把string2
看成一个池子。SELECT trim(leading 't' from 'test') FROM dual;
--------
'est'
SELECT trim(trailing 't' from 'test') FROM dual;
---------
'tes'
SELECT trim(both 't' from 'test') FROM dual;
--------
'es'
SELECT trim(both 'te' from 'test') FROM dual;
---------
提示截取集仅能有一个字符
SELECT rtrim('aaaaminb','main') FROM dual;
--------
'aaaaminb'
SELECT rtrim('aaaaminb','mainb') FROM dual;
--------
返回结果为空
SELECT ltrim('ccsbcminb','cb') FROM dual;
--------
'sbcminb'
abs(n)
:绝对值函数
round(n, m)
:四舍五入
ROUND(25.328)=25;ROUND(25.328, 2)=25.33;ROUND(25.328, -1)=30
trunc(n, m)
: 截取数字
n
需要截尾取整的数字,m
用于指定取整精度的数字,m
的默认值为 0。
trunc()
函数截取时不进行四舍五入。
9.select trunc(123.458) from dual --123
10.select trunc(123.458,0) from dual --123
11.select trunc(123.458,1) from dual --123.4
12.select trunc(123.458,-1) from dual --120
13.select trunc(123.458,-4) from dual --0
14.select trunc(123.458,4) from dual --123.458
15.select trunc(123) from dual --123
16.select trunc(123,1) from dual --123
17.select trunc(123,-1) from dual --120
mod(m, n)
:MOD
返回m
除以n
的余数,如果n
是0,返回m
select mod(5,2), mod(10,2) from dual;
--------
1 0
ceil(n), floor(n)
:取整
ceil(n)
取大于等于数值n
的最小整数(向上取整);floor(n)
取小于等于数值n
的最大整数(向下取整);select ceil(9.5) from dual;
--------
10
select floor(9.5) from dual;
--------
9
sqrt(n)
:开根号
sqrt(4) ⇒ 4 \sqrt{4} 4 ⇒ 2
power(n,m)
:指数
power(2, 3) ⇒ 23 ⇒ 8
SYSDATE
:当前日期
select sysdate - 1 昨天, sysdate 今天, sysdate + 1 明天 from dual;
--------
2019/10/23 10:43:44 2019/10/24 10:43:44 2019/10/25 10:43:44
#日期转字符串
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
--------
'2019-10-24 10:45:13'
MONTHS_BETWEEN(d1, d2)
:返回日期d1
和d2
之间相差的月数。d1
大于d2
结果为正数,否则为负数。
select months_between(date'2019-10-01',date'1994-01-01') 月数差 from dual;
--------
309
ADD_MONTHS(date, integer)
:返回date
之后或者之前integer
月份所对应的日期时间
SELECT ADD_MONTHS(date'1994-01-01', 120) FROM dual; --10年后
--------
2004/1/1
NEXT_DAY(date, char)
:该函数用于返回特定日期下一周的日期. date
用于指定日期时间值,char
用于指定工作日。
AMERICAN
,那么周一对应于"MONDAY
";简体中文
,那么周一对应于"星期一
"。select NEXT_DAY(date'2019-10-24','星期六') from dual;
--------
2019/10/26
LAST_DAY(date)
:返回特定日期所在月份的最后一天
select LAST_DAY(date'2019-10-01') from dual;
--------
2019/10/31
extract(datetime)
:提取日期特定部分
select extract(year from sysdate) year,
extract(minute from timestamp '2010-6-19 12:23:01') min
from dual;
--------
2019 23
ROUND
:对日期进行四舍五入
select sysdate,round(sysdate,'mi') from dual;
--------
2019/10/24 11:13:57 2019/10/24 11:14:00
select sysdate,round(sysdate,'hh') from dual;
--------
2019/10/24 11:13:57 2019/10/24 11:00:00
select sysdate,round(sysdate,'dd') from dual;
--------
2019/10/24 11:13:57 2019/10/24
select sysdate,round(sysdate,'mm') from dual;
--------
2019/10/24 11:13:58 2019/11/1
select sysdate,round(sysdate,'yy') from dual;
--------
2019/10/24 11:13:58 2020/1/1
select sysdate,round(sysdate,'yy') from dual;
--------
2019/10/24 11:13:58 2020/1/1
TRUNC(date, m)
:截取日期
select sysdate,trunc(sysdate) from dual;
--------
2019/10/24 11:18:22 2019/10/24
select sysdate,trunc(sysdate, 'mm') from dual;--返回当月第一天.
--------
2019/10/24 11:18:23 2019/10/1
select sysdate,trunc(sysdate,'yy') from dual;--返回当年第一天
--------
2019/10/24 11:18:23 2019/1/1
select sysdate,trunc(sysdate,'dd') from dual;--返回当前年月日
--------
2019/10/24 11:18:23 2019/10/24
select sysdate,trunc(sysdate,'yyyy') from dual;--返回当年第一天
--------
2019/10/24 11:18:23 2019/1/1
select sysdate,trunc(sysdate,'d') from dual;--返回当前星期的第一天
--------
2019/10/24 11:18:24 2019/10/20
select sysdate,trunc(sysdate, 'hh') from dual;
--------
2019/10/24 11:18:24 2019/10/24 11:00:00
select sysdate,trunc(sysdate, 'mi') from dual;
--------
2019/10/24 11:18:24 2019/10/24 11:18:00
日期类型 -> 字符类型(使用TO_CHAR())、字符类型 -> 日期类型(使用TO_DATE())
字符类型 -> 数值类型(使用TO_NUMBER())、数值类型 -> 字符类型(使用TO_CHAR())
TO_CHAR(n)
to_char(date)
SELECT sysdate,to_char(sysdate,'yyyy-mm-dd') FROM dual;
--------
2019/10/24 11:35:46 '2019-10-24'
SELECT sysdate,to_char(sysdate,'YYYY"年"MM"月"DD"日"') FROM dual;
--------
2019/10/24 11:35:46 '2019年10月24日'
select to_char(sysdate,'day') from dual;
--------
星期三
to_char(number)
常用元素 | 说明 |
---|---|
9 | 显示数字,并且会忽略前面的 0 |
0 | 显示数字,如果位数不够,会用 0 补齐 |
. | 在指定位置显示小数点 |
, | 在指定位置显示逗号 |
$ | 在数字前加上美元符号 |
L | 在数字前加上本地货币符号 |
SELECT 800, to_char(800, 'L00,000,000.00') from dual;
--------
800 ¥00,000,800.00
SELECT 800, to_char(800, '$00,000,000.00') from dual;
--------
800 $00,000,800.00
SELECT 800, to_char(800, 'L99,999,999.99') from dual;
--------
800 ¥800.00
SELECT 800, to_char(800, '$99,999,999.99') from dual;
--------
800 $800.00
to_date(str, char)
:字符串转为日期,需要指明格式。
SELECT to_date('1994-01-01','yyyy-mm-dd') FROM dual;
--------
1994/1/1
TO_NUMBER
:字符串转换成数值
SELECT to_number('800','999') FROM dual;
SELECT to_number('¥800','L999') FROM dual;
SELECT to_number('$800','$999') FROM dual;
--------
以上结果都为 800
listagg(n) within group(order by ...)
listagg 函数有两个参数:
1、 要合并的列名
2、 自定义连接符号
☆LISTAGG 函数既是分析函数,也是聚合函数
所以,它有两种用法:
1、分析函数,如: row_number()、rank()、dense_rank() 等,用法相似
listagg(合并字段, 连接符) within group(order by 合并的字段的排序) over(partition by 分组字段)
2、聚合函数,如:sum()、count()、avg()等,用法相似
listagg(合并字段, 连接符) within group(order by 合并字段排序) --后面跟 group by 语句
wm_concat(n)
:默认CLOB,可用to_char转换
SELECT u.account,to_char(wm_concat(u.account) over(partition by u.type)) FROM sys_sec_user u where u.type = '1';
SELECT u.account,listagg(u.account,',') within group(order by u.account) over(partition by u.type) FROM sys_sec_user u where u.type = '1';
select *
from SalesList pivot(
max(salesNum) for shangPin in ( --shangPin 即要转成列的字段
'上衣' as 上衣, --max(salesNum) 此处必须为聚合函数,
'裤子' as 裤子, --in () 对要转成列的每一个值指定一个列名
'袜子' as 袜子,
'帽子' as 帽子
)
)
where 1 = 1;
decode(字段,条件1,表达式1,条件2,表达式2,...表达式n)
SELECT decode('haha','haha',0,2) FROM dual;
--------
0
SELECT decode('hah','haha',0,2) FROM dual;
--------
2
1、格式一
case 字段
when 条件1 then 表达式1
when 条件2 then 表达式2
else 表达式n
end
2、格式二
case when
条件1 then 表达式1
when
条件2 then 表达式2
else
表达式n
end
--在 user1 下赋予权限
grant select on user1.table_name to user2;
--此时在 user2 用户下查询是
SELECT * FROM user1.table_name ;
--想要去掉前缀,得创建同义词 table_name 对应 user1.table_name
create synonym table_name for user1.table_name ;
--在 user1 下赋予权限
grant execute on user1.func_name to user2;
--此时在 user2 用户下查询是
SELECT * FROM user1.table_name ;
--想要去掉前缀,得创建同义词 func_name 对应 user1.func_name
create synonym func_name for user1.func_name ;
https://blog.csdn.net/wulex/article/details/83860001
https://www.cnblogs.com/liu-wang/p/8298573.html
https://www.bbsmax.com/A/ZOJPryKxdv/