1. 命令方式操作数据库(采用SQL*Plus)
1.1 创建表
1.1.1 基本语法格式
CREATE TABLE[<用户方案名>]<表名>
(
<列名1> <数据类型> [DEFAULT <默认值>] [<列约束>]
<列名2> <数据类型> [DEFAULT <默认值>] [<列约束>]
[,...n]
<表约束>[,...n]
)
[AS<子查询>]
1.1.2 说明
用户方案名
DEFAULT
列约束
定义一个完整性约束作为列定义的一部分,该子句的语法为:
表约束
AS<子查询>
表示将由子查询返回的行插入到所创建的表中。
示例:
1.2 修改表
1.2.1 语法格式
ALTER TABLE <表名>
ADD (<列定义1>, <列定义2>, ...),
MODIFY (<列修改1>, <列修改2>, ...),
DROP (<列名1>, <列名2>, ...);
1.2.2 说明
删除 PRIMARY KEY 或 UNIQUE 约束前的注意事项
解释:
1.3 删除表
1.3.1 语法格式
DROP TABLE[<用户方案名>]<表名>
1.4 插入记录
1.4.1 语法格式1
INSERT INTO<表名>[(<列名1)>,(<列名2>,...n)]
VALUES(<列值1>,<列值2>,...n)
示例:
同样可以使用 INSERT 语句把一个表中的部分数据插入到另一个表中,但结果集中每行数据集的字段数、字段的数据类型要与被操作的表完全一致。
1.4.2 语法格式2
INSERT INTO<表名>
<结果集>
其中,<结果集>是一个由 SELECT 语句查询所得到的新表。
如果要将 table1
中的部分数据插入到 table2
中,可以使用以下 SQL 语句:
INSERT INTO table2 (id, name, age)
SELECT id, name, age
FROM table1
WHERE age > 30;
COMMIT;
1.5 删除记录
1.5.1 DELETE 语句
DELETE FROM <表名> [WHERE <条件>];
删除 table1
中所有年龄大于30的记录:
DELETE FROM table1 WHERE age > 30;
1.5.2 TRUNCATE TABLE 语句
如果要删除一个大表里的全部记录,可以用此语句,他可以释放占用的数据块表空间,此操作不可回退。语法格式为:
TRUNCATE TABLE <表名>;
删除 table1
中所有记录,并释放表空间:
TRUNCATE TABLE table1;
1.6 修改记录
UPDATE 语句可以用来修改表总的数据行,语法格式为:
UPDATE<表名>
SET <列名>={<新值>|<表达式>}[,...n]
[WHERE <条件表达式>]
示例:
UPDATE XSB
SET 备注='辅修计算机专业'
WHERE 学号='15014';
UPDATE a
SET 总学分=总学分+5;
2. 数据库的查询和视图
2.1 选择、投影、连接
2.1.1 选择
选择(Selection),简单来说就是通过一定条件把自己所需要的数据检索出来。选择是单目运算,其对象是一个表。该运算按给定的条件,从表中选出满足条件的行形成一个新表,作为运算结果。
假设有一个表 Employees
,包含以下列:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
1 | John | Doe | 30 | HR |
2 | Jane | Smith | 25 | IT |
3 | Mike | Brown | 40 | Sales |
如果我们只选择 Age
大于 30 的员工,SQL 查询如下:
SELECT *
FROM Employees
WHERE Age > 30;
查询结果为:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
3 | Mike | Brown | 40 | Sales |
2.1.2 投影
投影(Projection)也是单目运算。投影就是选择表中指定的列,这样在查询结果中只显示指定数据列,减少了显示的数据量,也可调高查询的性能。
假设我们仍然使用上面的 Employees
表,如果我们只对 FirstName
和 Department
进行投影,SQL 查询如下:
SELECT FirstName, Department
FROM Employees;
查询结果为:
FirstName | Department |
---|---|
John | HR |
Jane | IT |
Mike | Sales |
组合投影和选择
我们也可以将投影和选择组合在一起使用。例如,我们想选择 Age
大于 30 的员工,并只显示他们的 FirstName
和 Department
,SQL 查询如下:
SELECT FirstName, Department
FROM Employees
WHERE Age > 30;
查询结果为:
FirstName | Department |
---|---|
Mike | Sales |
表的选择和投影运算分别从行和列两个方向上分割表,而以下要讨论的连接运算则是对两个表的操作。
2.1.3 连接
连接(JOIN)是把两个表的行按照给定的条件进行拼接而形成新表。
总结
2.2 数据库的查询
SELECT 语句主要的语法格式:
SELECT<列> /*指定要选择的列及其限定*/
FROM <表或视图> /*FROM 子句,指定表或视图*/
[WHERE <条件表达式>] /*WHERE 子句,指定查询条件*/
[GROUP BY <分组表达式>] /*GROUP BY 子句,指定分组表达式*/
[HAVING <分组条件表达式>] /*HAVING 子句,指定分组统计条件*/
[ORDER BY <排序表达式>[ASC|DESC]] /*ORDER BY 子句,指定排序表达式和顺序*/
下面讨论 SELECT 的基本语法和主要功能。
2.2.1 选择列
选择表中的列组成结果集,语法格式为:
SELECT [ALL|DISTINCT]<列名列表>
ALL
:默认行为,返回所有符合条件的行,包括重复行。DISTINCT
:只返回唯一的行,去除重复的行。
其中<列名列表>指出了结果的形式,其主要格式为:
{ * /*选择当前表或视图的所有列*/
|{<表名>|<视图>} * /*选择指定的表或视图的所有列*/
|{<列名>|<表达式>.}
[[AS}<列别名>] /*选择指定的列*/
|<列标题>=<列名表达式> /*选择指定列并更改列标题*/
}[,...n]
详细解释和示例
1. 选择当前表或视图的所有列
SELECT *
FROM Employees;
这个语句将选择 Employees
表中的所有列。
2. 选择指定的表或视图的所有列
SELECT Employees.*
FROM Employees;
这个语句也将选择 Employees
表中的所有列,与上面的语句效果相同。
3. 选择指定的列或表达式
SELECT FirstName, LastName, Age + 5 AS AgePlusFive
FROM Employees;
这个语句选择 FirstName
和 LastName
列,并选择一个表达式 Age + 5
,同时将其命名为 AgePlusFive
。
4. 为选定的列或表达式指定别名
SELECT FirstName AS FName, LastName AS LName, Age + 5 AS AgePlusFive
FROM Employees;
这个语句选择 FirstName
和 LastName
列,并分别将它们重命名为 FName
和 LName
。
5. 选择指定列或表达式并更改列标题
-- 查询,临时重命名列
SELECT FName = FirstName, LName = LastName
FROM Employees;
这一改变仅对当前查询有效,并不会对表的实际结构产生影响。
建议
为了确保 SQL 语句的可移植性和标准化,通常建议使用 AS
来指定别名,除非明确知道目标数据库系统支持 =
并且有特殊的需求。
组合示例
假设我们有一个表 Employees
,其结构如下:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
1 | John | Doe | 30 | HR |
2 | Jane | Smith | 25 | IT |
3 | Mike | Brown | 40 | Sales |
我们希望选择所有列并且对某些列进行别名处理:
SELECT EmployeeID, FirstName AS FName, LastName AS LName, Age + 5 AS AgePlusFive,Department
FROM Employees;
查询结果如下:
EmployeeID | FName | LName | AgePlusFive | Department |
---|---|---|---|---|
1 | John | Doe | 35 | HR |
2 | Jane | Smith | 30 | IT |
3 | Mike | Brown | 45 | Sales |
2.2.2 选择行
WHERE <表达式>
其中,<条件表达式>为查询条件,格式为:
<条件表达式>::=
{ [NOT]<判定运算>|(条件表达式)}
[{AND|OR} [NOT]{<判定运算>|(条件表达式)}]
}[,...n]
其中,<判定运算>的结果为TRUE,FALSE或UNKNOWN,经常用到的格式为:
<判定运算>::=
{ <表达式1>{=|<|<=|>|>=|<>|!=}<表达式2> /*比较运算*/
|<字符串表达式1>[NOT] LIKE<字符串表达式2>[ESCAPE'<转义字符>'] /*字符串匹配模式*/
|<表达式>[NOT] BETWEEN<表达式1>AND<表达式2> /*指定范围*/
|<表达式>IS [NOT] NULL /* 是否空值判断*/
|<表达式> [NOT] IN (<子查询>|<表达式>[,...n]) /*IN 子句*/
|EXIST(<子查询>) /*EXIST 子查询*/
}
判定运算包括比较运算、模式匹配、范围比较、空值比较和子查询。
比较时注意限制:
在使用字符串和日期数据进行比较时,注意要符合下面一些限制。
(1)字符串和日期必须是用单引号括起来。
(2)字符串数据区分大小写。
(3)日期数据的格式是敏感的,默认的日期格式是 DD-MM月-YY,可使用 ALTER SESSION 语句将默认日期修改为 YYYY-MM-DD。
SQL> SELECT SYSDATE AS CurrentDateTime
2 FROM dual;
CURRENTDATETIM
--------------
16-6月 -24
SQL>
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';
2.2.2.1 表达式比较
<表达式1>{=|<|<=|>|>=|<>|!=}<表达式2>
2.2.2.2 模式匹配
<字符串表达式1>[NOT] LIKE<字符串表达式2>
通配符的功能介绍
假设我们有一个表 Employees
,其结构如下:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
1 | John | Doe | 30 | HR |
2 | Jane | Smith | 25 | IT |
3 | Mike | Brown | 40 | Sales |
2.2.2.3 范围比较
2.2.2.4 空值比较
语法格式
<表达式> IS [NOT] NULL
示例:
2.2.2.5 子查询
语法格式
<表达式> {=|<|<=|>|>=|<>|!=} (子查询)
<表达式> [NOT] IN (子查询)
<表达式> [NOT] EXISTS (子查询)
(1)比较子查询
SELECT EmployeeID, FirstName, LastName, Salary
FROM Employees
WHERE Salary = (SELECT MIN(Salary)
FROM Employees
WHERE DepartmentID = 10);
(2)IN 子查询
示例:
假设我们有两个表 Employees
和 Departments
,结构如下:
Employees
表:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
1 | John | Doe | 30 | HR |
2 | Jane | Smith | 25 | IT |
3 | Mike | Brown | 40 | Sales |
Departments
表:
Department | Location |
---|---|
HR | New York |
IT | San Francisco |
Sales | Chicago |
我们希望找到 IT
部门的员工:
SELECT *
FROM Employees
WHERE Department = (SELECT Department FROM Departments WHERE Department = 'IT');
结果:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
2 | Jane | Smith | 25 | IT |
我们希望找到不在 IT
部门的员工:
SELECT *
FROM Employees
WHERE Department <> (SELECT Department FROM Departments WHERE Department = 'IT');
结果:
EmployeeID | FirstName | LastName | Age | Department |
---|---|---|---|---|
1 | John | Doe | 30 | HR |
3 | Mike | Brown | 40 | Sales |
注意:IN 和 NOT IN 子查询只能返回一列数据。对于较复杂的查询,可使用嵌套的子查询。
查询未选修离散数学的学生情况:
SELECT 学号,姓名,专业,总学分
FROM XSB
WHERE 学号 NOT IN
(SELECT 学号
FROM CJB
WHERE 课程号 IN
(SELECT 课程号
FROM KCB
WHERE 课程号='离散数学'
)
);
(3) EXISTS 子查询
假设我们有以下两个表:
Students
表(学生表),结构如下:
StudentID | Name | Major |
---|---|---|
1 | Alice | CS |
2 | Bob | Math |
3 | Charlie | Physics |
4 | David | CS |
Enrollments
表(选课表),结构如下:
StudentID | CourseID |
---|---|
1 | 101 |
2 | 102 |
3 | 103 |
4 | 101 |
1 | 102 |
示例 1:EXISTS
查询所有选修了 101
课程的学生信息。
SELECT *
FROM Students
WHERE EXISTS (
SELECT 1
FROM Enrollments e
WHERE e.StudentID = s.StudentID AND e.CourseID = 101
);
解释:
- 外层查询从
Students
表中选择所有学生。 - 内层子查询从
Enrollments
表中查找CourseID
为101
的记录,并且匹配Students
表中的StudentID
。 EXISTS
只需检查子查询是否返回任何记录。如果子查询返回至少一条记录,则EXISTS
返回TRUE
,否则返回FALSE
。- 最终结果是所有选修了
101
课程的学生。
结果:
StudentID | Name | Major |
---|---|---|
1 | Alice | CS |
4 | David | CS |
示例 2:NOT EXISTS
查询所有没有选修 101
课程的学生信息。
SELECT *
FROM Students
WHERE NOT EXISTS (
SELECT 1
FROM Enrollments e
WHERE e.StudentID = s.StudentID AND e.CourseID = 101
);
无论子查询中是 SELECT 1
、SELECT *
还是 SELECT e.CourseID
,效果都是相同的,因为 EXISTS
子句只关心子查询是否返回了至少一条记录。
结果:
StudentID | Name | Major |
---|---|---|
2 | Bob | Math |
3 | Charlie | Physics |
2.2.3 查询对象
前面介绍了 SELECT 选择表的列和行的操作,这里介绍 SELECT 查询对象(即数据源)的构成形式。
查找与 151101 号同学所选修课程一致的同学的学号:
SELECT DISTINCT 学号
FROM CJB 成绩1
WHERE NOT EXISTS
(SELECT *
FROM CJB 成绩2
WHERE 成绩2.学号='151101'AND NOT EXISTS
(SELECT *
FROM CJB 成绩3
WHERE 成绩3.学号=成绩1.学号
AND 成绩3.课程号=成绩2.课程号
)
);
2.2.4 连接
连接是二元运算,可以对两个或多个表进行查询,结果通常是含有参加连接运算的两个(或多个)表指定列的表。
2.2.4.1 连接谓词
可以在 SELECT 语句的 WHERE 子句中使用比较运算符给出连接条件对表进行连接,将这种表现形式称为连接谓词。
SELECT XSB.*,CJB.*
FROM XSB,CJB
WHERE XSB.学号=CJB.学号;
若选择的字段名在各个表中是唯一的,则可以省略字段名前的表名。例如:
SELECT XSB.*,CJB.课程号,成绩
FROM XSB,CJB
WHERE XSB.学号=CJB.学号;
连接和子查询可能都要涉及两个或多个表,区别是连接可以合并两个或多个表的数据,而带子查询的 SELECT 语句的结果只能来自一个表,子查询的结果是用来作为选择结果数据时进行参照的。
有的查询既可以使用子查询也可以使用连接表达。通常,使用子查询表达式可以将一个复杂的查询分解为一系列逻辑步骤,条理清晰;而使用连接表达有执行速度快的优点。因此,应尽量使用连接表示查询。
2.2.4.2 以 JOIN 关键字指定的连接
连接表的格式:
<表名><连接类型><表名>ON<条件表达式>
|<表名>CROSS JOIN<表名>
|<连接表>
其中,<连接类型>的格式:
<连接类型>::=
{INNER|{LEFT|RIGHT|FULL} [OUTER] CROSS JOIN
2.2.5 汇总
2.2.6 排序
在 Oracle 中,可以使用 ORDER BY
子句对查询结果进行排序。默认情况下,排序是按升序 (ASC),也可以指定为降序 (DESC)。
示例:
按姓氏升序排序:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEES
ORDER BY LAST_NAME ASC;
按工资降序排序:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEES
ORDER BY SALARY DESC;
按姓氏升序、工资降序排序:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEES
ORDER BY LAST_NAME ASC, SALARY DESC;
2.2.7 合并
Oracle 提供了几种合并查询结果的方法,包括 UNION
, UNION ALL
, INTERSECT
和 MINUS
。
UNION 和 UNION ALL:
UNION
用于合并两个查询结果,默认去除重复记录。UNION ALL
也用于合并两个查询结果,但不去除重复记录。
示例:
假设有两个表 EMPLOYEES
和 MANAGERS
,结构如下:
- EMPLOYEES: EMPLOYEE_ID, FIRST_NAME, LAST_NAME
- MANAGERS: MANAGER_ID, FIRST_NAME, LAST_NAME
使用 UNION 合并两个表中的记录:
SELECT FIRST_NAME, LAST_NAME
FROM EMPLOYEES
UNION
SELECT FIRST_NAME, LAST_NAME
FROM MANAGERS;
使用 UNION ALL 合并两个表中的记录:
SELECT FIRST_NAME, LAST_NAME
FROM EMPLOYEES
UNION ALL
SELECT FIRST_NAME, LAST_NAME
FROM MANAGERS;
INTERSECT:
INTERSECT
返回两个查询的交集,即同时存在于两个查询结果中的记录。
示例:
查询员工和经理中都存在的名字:
SELECT FIRST_NAME, LAST_NAME
FROM EMPLOYEES
INTERSECT
SELECT FIRST_NAME, LAST_NAME
FROM MANAGERS;
MINUS:
MINUS
返回在第一个查询中存在但在第二个查询中不存在的记录。
示例:
查询在员工表中存在但不在经理表中的名字:
SELECT FIRST_NAME, LAST_NAME
FROM EMPLOYEES
MINUS
SELECT FIRST_NAME, LAST_NAME
FROM MANAGERS;
2.3 数据库视图
2.3.1 视图的概念
2.3.2 创建视图
2.3.3 查询视图
视图创建后,可以像查询表一样查询视图。
查询刚刚创建的视图:
SELECT *
FROM emp_dept_view;
2.3.4 更新视图
2.3.5 修改视图的定义
可以使用 CREATE OR REPLACE VIEW
语句来修改视图的定义。
CREATE OR REPLACE VIEW <视图名>
AS
SELECT <列名>
FROM <表名>
WHERE <条件表达式>;
2.3.6 删除视图
DROP VIEW <视图名>;
2.4 含替换变量的查询
Oracle SQL*Plus 提供了使用替换变量的功能,允许用户在运行时输入值,从而提高查询的灵活性。常用的替换变量有单一替换变量(&
)、多次替换变量(&&
),以及定义和接受命令(DEFINE
和 ACCEPT
)。
2.4.1 &替换变量
&
替换变量用于在查询中提示用户输入值。每次执行查询时,用户都会被提示输入一个值。
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = &employee_id;
注意:
替换变量是字符类型或日期类型的数据,输入值必须要用单引号括起来。为了在输入数据是不需要输入单引号,也可以使用在 SELECT 语句中把变量用单引号括起来。
因此,上面的也可以使用如下语句:
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = &'employee_id';
为了在执行变量替换之前,显示如何执行替换的值,可以使用 SET VERIFY 命令
SET VERIFY ON
示例:
SQL> SELECT *
2 FROM EMPLOYEES
3 WHERE HOURLY_RATE>&HOURLY_RATE;
输入 hourly_rate 的值: 20
原值 3: WHERE HOURLY_RATE>&HOURLY_RATE
新值 3: WHERE HOURLY_RATE>20
EMPLOYEE_ID EMPLOYEE_NAME HOURLY_RATE
----------- -------------------- -----------
4 Emily 22.25
8 Amy 21.5
9 Michael 23
10 Michelle 24.75
2.4.2 &&替换变量
&&
替换变量用于多次使用同一个值。用户在第一次输入后,后续的查询中将不会再次提示输入。
查询选修课程超过两门且成绩在75以上的学生的学号:
SELECT &&column
FROM CJB
WHERE 成绩>=75
GROUP BY &column
HAVING COUNT(*)>2;
用户输入 学号 后,SQL*Plus 会记住这个值。在同一会话中,再次使用 &&column
时,不会提示用户再次输入。
2.4.3 DEFINE 和 ACCEPT 命令
DEFINE
命令:用于创建一个替换变量,并赋予初始值。DEFINE
命令创建的变量在会话期间有效,直到被显式取消(UNDEFINE
)。
DEFINE [<变量名>[=<变量值>]]
使用 DEFINE
变量
- 使用
DEFINE
命令
假设我们使用 DEFINE
命令创建一个变量,并为其赋值:
DEFINE employee_id = 101
在这个例子中,employee_id
是一个字符类型(CHAR)的变量,尽管它的值看起来像是一个数字。
-- 设置 VERIFY 模式以显示变量替换
SET VERIFY ON;
-- 创建一个字符类型的变量
DEFINE employee_id = 101
-- 使用变量进行查询
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = &employee_id;
使用 UNDEFINE
取消变量
可以使用 UNDEFINE
命令取消已定义的变量,这样下一次使用该变量时会提示用户重新输入值:
-- 取消变量定义
UNDEFINE employee_id
-- 再次提示用户输入变量值
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = &employee_id;
ACCEPT
命令
用于提示用户输入一个值,并将该值赋予一个变量。与 DEFINE
不同的是,ACCEPT
会在执行时提示用户输入。
ACCEPT <变量名> [<数据类型>] [FORMAT<格式模式>]
[PROMPT <提示文本>] [HIDE]
基本用法
ACCEPT employee_id PROMPT 'Enter Employee ID: '
/*输入一个id*/
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = &employee_id;
指定数据类型和格式模式
ACCEPT salary NUMBER FORMAT '99999.99' PROMPT 'Enter Salary: '
/*同上*/
SELECT *
FROM EMPLOYEES
WHERE SALARY > &salary;
隐藏输入内容
ACCEPT password CHAR FORMAT 'X' HIDE PROMPT 'Enter Password: '
SELECT *
FROM USERS
WHERE PASSWORD = '&password';
说明:ACCEPT password CHAR FORMAT 'X' HIDE
:定义一个名为 password
的字符变量,指定格式模式为 'X'
(隐藏输入内容),并且输入时不显示用户输入内容。
本篇分享到此为止,感谢支持~🌹