在 Oracle 数据库的知识体系中,数据查询语言(DQL)无疑是最为常用且关键的部分之一。对于 Java 全栈开发者而言,熟练掌握 DQL 不仅能高效地从数据库中获取所需数据,更是构建强大后端应用的基石。通过 DQL,我们可以像一位经验丰富的图书管理员在庞大的数据库书库中,精准快速地找到每一本 “数据之书”。接下来,让我们深入探索 Oracle 数据库 DQL 的奥秘。
目录
一、DQL 查询数据
(一)语法结构总览
DQL 的基本语法为:
select 字段列表 from 表的表名 [where 条件筛选] [order by 排序样本] [having 聚合过滤] [group by 分组字段];
这一语法结构如同一个精密的工具,每个部分都有其独特的作用,协同工作以实现多样化的数据查询需求。
(二)查询所有数据
- 指定字段查询:当我们只需要获取表中的部分字段数据时,可明确指定字段列表。例如,从
book
表中查询id
、book_name
、author_name
和price
字段:
Select id,book_name,author_name,price from book;
- 全字段查询:若要获取表中的所有字段数据,使用通配符
*
即可:
Select *from book;
在 Java 全栈开发中,当我们构建一个简单的图书管理系统后端时,如果前端页面需要展示书籍的所有信息,那么使用Select *from book
查询出所有字段数据,再通过 Java 的数据库连接框架(如 MyBatis、Hibernate)将数据传递给前端展示。但在实际企业项目中,应谨慎使用*
,因为它可能会带来不必要的数据传输开销,特别是在表字段较多时。
(三)条件查询
条件查询允许我们根据特定条件筛选出符合要求的数据,这在实际应用中极为常见。
- 基本比较运算符:包括
=
(等于)、!=
或<>
(不等于)、>
(大于)、<
(小于)、>=
(大于等于)、<=
(小于等于)。例如,查询价格大于 50 的书籍:
select * from book where price > 50;
- 模糊查询:使用
like
关键字,结合通配符%
和_
进行模糊匹配。%
通配符:%
在后:以前面字符为基准,向后匹配 0 到 n 个字符。比如查询出版社名称以 “你干嘛” 开头的所有书籍:
select * from book where publish like '你干嘛%';
%
在前:以后面字符为基准,向前匹配 0 到 n 个字符。例如查询出版社名称以 “哎哟” 结尾的书籍:
select * from book where publish like '%哎哟';
%
在两侧:以中间字符为基准,向前后匹配 0 到 n 个字符。如查询出版社名称中包含 “干嘛” 的书籍:
select * from book where publish like '%干嘛%';
_
通配符:_
在后:以前面字符为基准,向后匹配 1 个字符。例如查询作者姓名为两个字且第二个字为 “辰” 的书籍:
select * from book where author_name like '辰_';
_
在前:以后面字符为基准,向前匹配 1 个字符。如查询作者姓名为三个字且第三个字为 “西” 的书籍:
select * from book where author_name like '__西';
_
在两侧:以中间字符为基准,向前后分别匹配 1 个字符。比如查询作者姓名三个字且中间字为 “东” 的书籍:
select * from book where author_name like '_东_';
在 Java 全栈开发的电商项目中,用户在搜索商品时,模糊查询就派上了大用场。前端用户输入关键词,后端通过构建类似的模糊查询语句,从数据库中检索出相关商品信息返回给用户。
3. 范围查询:
- 使用
in
关键字查询离散范围。例如,查询id
是 1、3、5 的书籍:
select * from book where id in (1,3,5);
- 使用
between and
查询连续范围。比如,查询价格在 50 到 80 之间的书籍:
select * from book where price between 50 and 80;
- 非 NULL 查询:通过
is null
和is not null
判断字段是否为空。例如,查询没有作者的书籍:
select * from book where author_name is null;
查询填写了作者的书籍:
select * from book where author_name is not null;
(四)去重查询
当查询结果中存在重复数据且我们希望去除这些重复时,使用distinct
关键字。例如,从book
表中查询不同的书籍名称和价格:
Select distinct book_name,price from book;
注意,distinct
关键字作用于其后的所有字段组合,并且通常不建议在其后加上唯一标识字段(如id
),因为这会使distinct
失去去重意义。在 Java 全栈开发中,当我们从数据库获取数据用于前端展示时,如果不希望出现重复数据影响用户体验,就可以使用distinct
进行去重操作。
(五)排序查询
排序查询用于对查询结果进行排序,使数据呈现更具条理性。
基本排序:语法为select字段列表 from 表的表名[where 条件筛选] [order by 排序样本];
,通过asc
(升序,可省略)和desc
(降序)指定排序方式。例如,查询出版社名称以 “宇宙” 开头的书籍,并按出版日期升序排列:
Select *from book where publish like ‘宇宙%’ order by publish_date asc;
按出版日期降序排列:
Select *from book where publish like ‘宇宙%’ order by publish_date desc;
复合排序:可以指定多个排序条件,先执行前面的排序条件,再执行后面的。例如,从book
表中先按价格升序,再按出版日期降序排序:
Select *from book order by price asc,publish_data desc;
在电商平台的 Java 全栈项目中,这种复合排序非常有用。比如商品展示页面,可能需要先按照销量进行降序,再按照价格进行升序,以展示热门且价格合理的商品。示例代码如下:
create table goods(
id number(3) primary key,
goods_name nvarchar2(20),
goods_type nvarchar2(20),
goods_price number(10,2),
goods_store number(3),
goods_sales number(3),
make_address nvarchar2(120)
);
INSERT INTO goods (id, goods_name, goods_type, goods_price, goods_store, goods_sales, make_address)
VALUES
(1, '苹果', '水果', 5.99, 100, 200, '山东烟台');
INSERT INTO goods (id, goods_name, goods_type, goods_price, goods_store, goods_sales, make_address)
VALUES
(2, '香蕉', '水果', 3.49, 150, 300, '海南三亚');
INSERT INTO goods (id, goods_name, goods_type, goods_price, goods_store, goods_sales, make_address)
VALUES
(3, '大米', '粮食', 25.75, 500, 1000, '黑龙江五常');
select * from goods where goods_type = '水果' order by goods_sales desc, goods_price asc;
二、系统函数
(一)聚合函数
聚合函数用于对一组数据进行计算,返回一个单一的值。
- Count():统计满足条件的数据行数。例如,统计
book
表中总共有多少条数据:
select count(*) from book;
统计作者名字不为空的书籍数量:
select count(author_name) from book;
统计书籍表中名字带 “童话” 的书籍数量:
select count(*) from book where author_name like '%童话%';
- Max():查询最大值。如查询关于天文书籍中最贵的价格:
select max(price) from book where author_name like '%天文%';
- Min():查询最小值。例如,查询关于天文书籍中最低的价格:
select min(price) from book where author_name like '%天文%';
- Avg():查询平均数。查询历史书籍售卖的平均价格,如果存在价格为 NULL 的情况,使用
nvl
函数将其转换为 0 后再求平均:
select avg(nvl(price,0)) from book where author_name like '%历史%';
- Sum():查询和。例如,查询科幻书籍售卖的总价:
select sum(price) from book where author_name like '%科幻%';
需要注意的是,max
、min
、avg
、sum
函数不能直接使用*
。在 Java 全栈开发中,聚合函数常用于统计报表功能。比如在一个财务系统中,使用sum
函数统计某段时间内的订单总金额,再通过 Java 代码将统计结果展示在报表页面上。
(二)字符串函数
字符串函数用于处理和操作字符串数据。
- 大小写转换:
upper
函数将字符串转换为大写。例如,将parents
表中email
字段的值转换为大写:
select id,name,upper(email) from parents;
lower
函数将字符串转换为小写:
select id,name,lower(email) from parents;
- 字符串拼接:使用
concat
函数进行字符串拼接。例如,查询parents
表中地址以 “成都” 开头的记录:
select * from parents where address like concat('成都','%');
也可以在虚拟表dual
中测试字符串拼接效果:
select concat('hello','world') from dual;
- 去除空格:
trim
函数用于去掉字符串两侧的空格。例如,处理parents
表中address
字段的空k格。
select id,name,trim(address) from parents;
- 字符串截取:
ubstr
函数从指定位置开始截取字符串。例如,从parents
表中address
字段的第 3 个字符开始截取:
select id,name,substr(address,3) from parents;
也可以指定截取长度。如从第 3 个字符开始截取长度为 4 的字符串:
select id,name,substr(address,3,4) from parents;
获取字符串长度:length
函数返回字符串的长度。例如,获取parents
表中address
字段值的长度:
select id,name,length(address) from parents;
字符串替换:replace
函数用于替换字符串中的指定部分。比如,将parents
表中address
字段里的 “市” 替换为 “国”:
select id,name,replace(address,'市','国') from parents;
(三)转换函数
日期格式化:使用to_char
函数对日期进行格式化。例如,从book
表中查询书籍信息,并将publish_date
字段格式化为yyyy - MM - dd
的形式:
select id,book_name,to_char(publish_date,'yyyy-MM-dd') as publish_date from book;
- 字符串转日期:
to_date
函数将字符串解析为日期类型。例如,在虚拟表dual
中将字符串'2010 - 10 - 10'
解析为日期:
select to_date('2010-10-10','yyyy-MM-dd') as birthday from dual;
- 字符串转数值:
to_number
函数将字符串转换为数值类型。例如,在虚拟表dual
中将字符串'123'
转换为数值:
select to_number('123') from dual;
- 条件转换:
- 使用
CASE WHEN
语句进行条件判断和转换。例如,在parents
表中根据gender
字段的值转换为对应的性别描述:
- 使用
select id,name,CASE gender
WHEN 0 THEN
'女'
WHEN 1 THEN
'男'
ELSE
'其它'
END as gender from parents;
decode
函数也可实现类似功能:
select id,name,decode(gender,0,'女',1,'男','其它') as gender from parents;
在 Java 全栈开发中,转换函数常用于数据格式的统一和处理。比如从数据库中获取的日期数据,通过to_char
函数格式化后,更方便在前端页面展示。
(四)数值函数
数值函数用于对数值进行各种运算。
- 四舍五入:
round
函数进行四舍五入,默认保留整数。例如,对3.1415926
进行四舍五入:
select round(3.1415926) from dual;
- 也可以指定保留小数位数。如保留 2 位小数:
select round(3.1415926,2) from dual;
- 取余:
mod
函数计算两个数相除的余数。例如,计算 10 除以 3 的余数:
select mod(10,3) from dual;
- 向上取整:
ceil
函数将数值向上取整。例如,对3.14
向上取整:
select ceil(3.14) from dual;
- 向下取整:
floor
函数将数值向下取整。例如,对3.14
向下取整:
select floor(3.14) from dual;
三、求交集、并集与差集
在处理多个查询结果集时,我们可以使用minus
(求差集)、intersect
(求交集)、union
(求并集)操作。
- 交集:例如,在
friend_info
表中查询 “小齐” 和 “蒲哥” 共同的好友:
select friend_name from friend_info where user_name = '小齐'
intersect
select friend_name from friend_info where user_name = '蒲哥';
- 并集:查询 “小齐” 和 “蒲哥” 的所有好友(去重):
select friend_name from friend_info where user_name = '小齐'
union
select friend_name from friend_info where user_name = '蒲哥';
需要注意union
和union all
的区别,union all
不会去重。例如,查询 “小齐” 和 “蒲哥” 的所有好友(不去重):
select friend_name from friend_info where user_name = '小齐'
union all
select friend_name from friend_info where user_name = '蒲哥';
在 Java 全栈开发的社交类应用中,这些集合操作可以用于好友推荐、兴趣匹配等功能。比如通过交集操作找到有共同兴趣爱好的用户,为用户推荐可能认识的人。
四、企业工作小技巧
- 查询优化:在企业项目中,数据量往往非常庞大。对于复杂的查询,尽量使用索引来提高查询效率。例如,如果经常根据作者姓名查询书籍,那么为
author_name
字段创建索引可以显著加快查询速度。同时,避免在where
条件中对字段进行函数操作,因为这会导致索引失效。 - 代码规范与注释:在 Java 全栈开发中,编写数据库查询相关代码时,要遵循良好的代码规范。例如,在使用 MyBatis 框架时,SQL 语句尽量写在 XML 文件中,并添加详细注释,说明每个查询的功能、参数含义以及预期返回结果。这不仅方便团队成员理解和维护代码,也有助于在出现问题时快速定位和解决。
- 数据安全与权限控制:在进行数据查询时,要严格控制用户权限。在数据库层面,通过角色和权限设置,确保不同用户只能查询其有权限访问的数据。在 Java 代码中,对用户输入进行严格的校验和过滤,防止 SQL 注入攻击,保障数据安全。
通过对 Oracle 数据库 DQL 的深入学习和实践,我们在数据查询和处理能力上有了显著提升。在未来的 Java 全栈开发旅程中,灵活运用这些知识,将为我们打造高效、稳定且安全的应用系统奠定坚实基础。