SQL:Structured Query Language
结构化查询语言,是用于访问和处理数据库的标准的计算机语言,不同数据库间语言存在差异
SQL 分为 DML、DCL、DQL、DDL 等
Oracle Database,甲骨文公司提供的通用数据库,是当前最流行的数据库之一
数据文件(dbf)
数据存储在数据库中,终究是存储在物理磁盘之上,数据文件就是数据库的物理存储单位
表空间(tablespace)
表空间是数据库对物理存储上相关数据文件的映射
一个数据库被划分为一到若干个表空间,至少有一个表空间
每个表空间由磁盘上一个或多个数据文件组成
一个数据文件只能属于一个表空间
用户(user)和模式(schema)
用户是用来连接数据库和访问数据库对象的,持有系统的权限及资源
schema 是数据对象的集合,包含了表、函数、包等等对象
Oracle 中的 schema 就是指一个用户下所有对象的集合
一个用户一般对应一个 schema,该用户的 schema 名等于用户名,并作为该用户缺省 schema
创建用户
create user 用户名 identified by 密码;
查看表空间信息
SELECT
*
FROM
Dba_Tablespaces;
查看表空间配置文件信息
SELECT
*
FROM
Dba_data_files;
创建表空间
CREATE TABLESPACE 表空间名 DATAFILE 配置文件存放位置 SIZE 配置文件大小
指定默认表空间
# 设置指定用户的默认表空间
ALTER USER 用户名 DEFAULT TABLESPACE 表空间名;
# 设置数据库的默认临时表空间
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp_tbs_name;
查看默认表空间
SELECT
default_tablespace
FROM
user_users;
给用户授权
GRANT DBA TO 用户名
创建数据表
CREATE TABLE USER(
ID NUMBER,
NAME VARCHAR2(32),
AGE NUMBER,
BIRTH DATE
)
几种字符串类型:
CHAR(n)
长度固定,不足自动补空格,汉字占 2 字节,字母 1 字节,n 为字节数
VARCHAR(n)
可变长度,汉字占 2 字节,字母 1 字节,n 为字节数
VARCHAR2(n)
非工业标准,保证版本兼容,占用与字符集相关,空串处理为 null,n 为字节数,最大 4000
NVARCHAR(n)
可变长度,Unicode 编码,n 为字符数
NVARCHAR2
汉字和字母统一占用两个字节
设置自增 ID
用来获取 ID 的自增序列
CREATE SEQUENCE SQ_USER_ID
MINVALUE 1 MAXVALUE 99999999
INCREMENT BY 1 START WITH 1
自动填充 ID 的触发器
CREATE OR REPLACE TRIGGER USER
BEFORE INSERT
ON USER
FOR EACH ROW
BEGIN
SELECT SQ_USER_ID.NEXTVAL INTO :NEW.ID FROM DUAL;
END;
insert
INSERT INTO table_name VALUES(value_1, value_2, value_3);
INSERT INTO table_name(column_1, column_3) VALUES(value_1, value_3);
delete
DELETE FROM
table_name
WHERE
column_1='xxx';
update
UPDATE
table_name
SET
column_1="xxx",
column_2="xxx"
WHERE column_3="xxx"
select
SELECT
column_1,
column_2
FROM
table_name;
where
表示查询条件,与 and/or 配合使用
SELECT
*
FROM
table_name
WHERE
(column_1='xxx'
AND column_2='xxx')
OR column_3='xxx';
distinct
用于获得唯一性记录,可以限制多个列
SELECT
DISTINCT column_1
FROM
table_name
order by
将查询的结果,按照一定的顺序进行排序,ASC 升序(默认),DESC 降序
如果是字符串,则按字母表顺序排序
order by 一般用在 SQL 语句的最后
SELECT
column_1, column_2
FROM
table_name
ORDER BY
column_1 DESC
group by
对记录集合进行分组
group by 后的字段表示按这些字段分组,按照这些字段组成一条记录,重复的属于同一组,最后返回这些分组
SELECT
name, age, sex
WHERE
sex='男'
GROUP BY
name, age, sex
分组之后 select 语句的真实操作目标为各个分组数据,每次循环处理的也是各个分组,而不是单条记录
having
having 多用于 group by 后对分组的筛选,功能类似 where,但是只能筛选分组后的查询结果中的字段
例如,查看 person 表的男生中每个名字的同名次数,并且展示次数大于 2 的分组
SELECT
name, COUNT(*) num
FROM
person
WHERE
sex='男'
GROUP BY
name
having
num > 2
嵌套查询
子查询是嵌套在查询语句中的查询语句,是完整的查询语句
子查询的结果集除了可以作为父查询 from 的数据表,还可以作为 where 子句查询条件
结果集只有一行,通常使用=
判断
结果集为单行单列,即一个值
SELECT
*
FROM
table_1 t1
WHERE
t1.t1_colum_1 = (
SELECT
t2_colum_1
FROM
table_2
)
结果集为单行多列,即一行记录
SELECT
*
FROM
table_1 t1
WHERE
(t1.t1_colum_1, t1.t1_colum_2) = (
SELECT
t2_colum_1, t2_colum_2
FROM
table_2
)
结果集有多行,主要使用三种操作符:IN、ANY、ALL
结果集为多行单列,即多个值
SELECT
*
FROM
table_1 t1
WHERE
t1.t1_colum_1 IN (
SELECT
t2_colum_1
FROM
table_2
)
结果集为多行多列,即多行记录
SELECT
*
FROM
table_1 t1
WHERE
(t1.t1_colum_1, t1.t1_colum_2) IN (
SELECT
t2_colum_1, t2_colum_1
FROM
table_2
)
IN 表示在多个值中进行匹配
= ANY 等价于 IN
< ANY 表示比子查询结果集中的最大的小
> ANY 表示比子查询中结果集中最小的大
<> ALL 等价于 NOT IN
< ALL 表示比子查询结果集中的最小的小
> ALL 表示比子查询中结果集中最大的大
需要注意:
<> ANY 表示与结果集中任意一条记录不等就返回真
<> ALL 表示与每一条记录都不等才返回真
此外,EXSITS 构用于判断子查询是否有数据返回,如果有则返回 true
SELECT
*
FROM
table_1
WHERE
EXSITS (
SELECT
column_1,
column_2
FROM
table_name
)
联合查询
UNION:将两个结果集进行并集操作,并剔除重复记录
UNION ALL:并集操作但不剔除重复记录,比 UNION 要快
SELECT column_1 FROM table_name1
UNION ALL
SELECT column_1 FROM table_name2
UNION 需要两个结果集拥有同样的列数,不要求列名相同
UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名
同样的,INTERSECT 用于交集操作,MINUS 用于差集操作
连接查询
左连接:LEFT JOIN,返回左表所有行,取右表数据进行匹配,匹配不到的为空
右连接:RIGHT JOIN,返回右表所有行,取左表数据进行匹配,匹配不到的为空
内连接:INNER JOIN,返回两个表中匹配的行
SELECT
t1.cloumn_1,
t2.cloumn_1,
t2.cloumn_2
FROM
table_1 t1
LEFT JOIN
table_2 t2
ON
table_name1.cloumn_1 = table_name2.cloumn_1
自身连接:
SELECT
t1.id,
t2.id
FROM
table1 t1, table_1 t2
WHERE
t1.id = t2.parentId
聚合函数
AVG:求平均值
SUM:求和
COUNT:统计数量
MIN、MAX:求最大、最小记录
聚合函数对一组数据进行操作,返回一行结果
当需要返回其他字段时,需要按该字段分组
SELECT
SUM(cloumn_1)
FROM
table_1;
SELECT
cloumn_1, SUM(cloumn_2)
FROM
table_1
GROUP BY
cloumn_1;
字符串
LENGTH(str):返回字符串长度
SUBSTR(str, start[, length]):从 start 处开始,截取 length 个字符,缺省 length 默认到结尾
SELECT
*
FROM
table_1
WHERE
SUBSTR(id, 2) = 'xxx'
SUBSTR 的第二个参数从 1 开始,表示第一个字符。若是 -1 则表示倒数第一个,以此类推
INSTR:查询字符串在另一字符串中的位置
SELECT
INSTR('hello', 'l', 1, 2)
FROM
DUAL;
INSTR(orign, target[, start, nth]):查询在 origin 中 target 的位置,从 start 开始,查找第 nth 个 target
若 start 为负数,则从后往前查找,但返回值还是从前往后数,返回 0 表示没有查到
格式化
TO_DATE(str[, fmt]):将字符串以 fmt 格式转为日期类型
TO_CHAR(d[, fmt]):将日期或数字转为 fmt 格式的字符串
SELECT
TO_CHAR(TO_DATE('20210314', 'yyyymmdd'))
FROM
DUAL;
TO_CHAR 的 fmt 参数:
- iw:获取是第几周
- yyyy:获取年
- mm:获取月
- dd:获取日
- day:获取是周几
- hh24:获取 24 制小时
- mi:获取分种
- ss:获取秒
日期
SYSDATE:获取当前时间
ADD_MONTHS(d,n):d 指定日期,n 表示要加的月数量,可为负数
LAST_DAY(d):获取指定时间当月的最后一天
NEXT_DAY(d, '星期一'):获取下一周的周一
TRUNC(d[, fmt]):截取时间,常用来获取时间范围的第一天
TRUNC(SYSDATE, 'yy') 本年第一天
TRUNC(SYSDATE, 'q') 本季度第一天
TRUNC(SYSDATE, 'mm') 本月第一天
TRUNC(SYSDATE, 'd') 本周第一天,周日开始
举例:
获取最近 7 天(包括当天)
SELECT
TO_CHAR(SYSDATE - 6, 'yyyy-mm-dd hh24:mi:ss')
FROM
dual;
获取最近 4 周(包括当前周)
SELECT
TO_CHAR(TRUNC(SYSDATE - 21, 'd') + 1, 'yyyy-mm-dd hh24:mi:ss')
FROM
dual;
获取最近 3 个月(包括当前月)
SELECT
TO_CHAR(TRUNC(ADD_MONTHS(SYSDATE, -2), 'mm'), 'yyyy-mm-dd hh24:mi:ss')
FROM
dual;
获取当前季度第一天
SELECT
TO_CHAR(TRUNC(SYSDATE, 'q'), 'yyyy-mm-dd hh24:mi:ss')
FROM
dual;
获取上个季度第一天
SELECT
TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE, 'q'), -3), 'yyyy-mm-dd hh24:mi:ss')
FROM
dual;
数字
ABS:求绝对值
CEIL:向上取整
FLOOR:向下取整
ROUND(x, y):x 在第 y 位四舍五入
判断
NVL(x, v):x 为空,返回 v,否则返回 x
NVL2(x, v1, v2):x 为空,返回 v2,否则返回 v1
DECODE(x, v1, r1, v2, r2, ...vn, rn, default):类似于 if-else,x 等于 v1 则返回 r1,以此类推,直到缺省值
示例,查询学生,要求年龄在 20 以上的显示 20 以上,20 以下的显示 20 以下,20 的显示正好 20:
select t.id,
t.name,
t.age,
DECODE(SIGN(t.age - 20),
1,
'20 以上',
-1,
'20 以下',
0,
'正好 20',
'未知') sex
from student t
CASE WHEN:类似于 switch-case,比 DECODE 复杂且灵活,在其他数据库中也有该函数
上面示例用 case when 实现:
select t.id,
t.name,
t.age,
(CASE
WHEN t.age = 20 THEN '正好 20'
WHEN t.age < 20 THEN '20 以下'
ELSE '20 以上'
END) sex
from student t