Oracle 的查询功能非常强大,可以满意各种复杂的查询需求。 基本查询:可以使用简朴的 SELECT 语句查询表中的数据。例如,SELECT * FROM employees; 可以查询 employees 表中的全部数据。还可以指定特定的列进行查询,如 SELECT employee_id, first_name FROM employees;。可以使用别名来重命名列名,方便阅读和理解查询效果,例如 SELECT employee_id AS id, first_name AS fname FROM employees;。使用 DISTINCT 关键字可以去除重复值,如 SELECT DISTINCT department_id FROM employees;。 带条件查询:可以使用 WHERE 子句来添加查询条件。例如,查询工资大于 5000 的员工信息,可以使用 SELECT * FROM employees WHERE salary > 5000;。条件判定运算符包括 =、<、>、<=、>=、!= 等。还可以使用条件毗连符 AND、OR、NOT 来组合多个条件。例如,查询工资大于 5000 且部门为销售部的员工信息,可以使用 SELECT * FROM employees WHERE salary > 5000 AND department = ‘销售部’;。区间判定可以使用 BETWEEN…AND 操纵符,例如查询工资在 4000 到 6000 之间的员工信息,可以使用 SELECT * FROM employees WHERE salary BETWEEN 4000 AND 6000;。还可以使用 IN 操纵符来查询列值在指定列表中的数据,例如查询部门为销售部、市场部、研发部的员工信息,可以使用 SELECT * FROM employees WHERE department IN (‘销售部’, ‘市场部’, ‘研发部’);。暗昧查询可以使用 LIKE 关键字,通配符 % 表示零个或多个恣意字符,_ 表示一个恣意字符。例如,查询姓王且名字长度为两个字的员工信息,可以使用 SELECT * FROM employees WHERE first_name LIKE ‘王_’;。 排序与分组查询:可以使用 ORDER BY 子句对查询效果进行排序。默认是升序排序,可以使用 ASC 关键字明白指定升序,使用 DESC 关键字指定降序。例如,查询员工信息并按照工资降序排序,可以使用 SELECT * FROM employees ORDER BY salary DESC;。分组查询可以使用 GROUP BY 子句,把具有相同值的多条记录当成一组进行处置处罚。例如,查询每个部门的员工人数,可以使用 SELECT department_id, COUNT() FROM employees GROUP BY department_id;。在分组查询中,可以使用 HAVING 子句进行进一步的过滤,例如查询员工人数大于 10 的部门信息,可以使用 SELECT department_id, COUNT() FROM employees GROUP BY department_id HAVING COUNT(*) > 10;。
(二)备份与恢复
备份压缩:可以选择在备份下令里表现指定压缩选项,如 BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;(仅对 1,5 文件压缩备份)、BACKUP AS COMPRESSED BACKUPSET DATAFILE 1,5;。也可以设置 RMAN 指定压缩选项,如 CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO COMPRESSED BACKUPSET;(备份压缩到指定路径)、backup as Compressed backupset database format 'd:\oracle\backup\%U.dbf’plus archivelog for。
恢复时点恢复(PITR):将数据库恢复到某个特定的时间点。先关闭数据库,启动到装载模式,分配通道,设置恢复时间点 SET UNTIL TIME “TO_DATE(‘2023-10-01 12:00:00’, ‘YYYY-MM-DD HH24:MI:SS’)”;,恢复数据库 RESTORE DATABASE;,恢复数据库 RECOVER DATABASE;,最后打开数据库并重置日志 ALTER DATABASE OPEN RESETLOGS;。
四、高级功能探索
(一)数据库优化
数据库优化对于提高 Oracle 数据库的性能至关重要。执行计划分析和索引管理是两个重要的优化方法。 执行计划分析:
执行计划分析可以帮助我们了解 SQL 语句的执行方式和性能瓶颈。Oracle 数据库提供了多种方式来查察执行计划,例如使用 EXPLAIN PLAN 语句或者在 SQL Developer 等工具中查察执行计划。执行计划中包含了多个重要的字段,如基数(Rows)、字节(Bytes)和泯灭(COST)等。基数表示当前操纵的返回效果集行数,字节表示执行该步调后返回的字节数,泯灭则是 CPU 泯灭,用于说明 SQL 执行的代价,理论上越小越好。常见的执行计划类型包括 TABLE ACCESS FULL(全表扫描)、TABLE ACCESS BY ROWID(通过 ROWID 的表存取)、TABLE ACCESS BY INDEX SCAN(索引扫描)等。例如,假设我们有一个较大的表 LARGE_TABLE,且 username 列上没有索引,运行 SELECT * FROM LARGE_TABLE where USERNAME = ‘TEST’; 语句时,执行计划可能表现为 TABLE ACCESS FULL LARGE_TABLE [65001] [ANALYZED],这表明进行了全表扫描。 索引管理:
索引是提高数据库查询性能的重要本领,但不准确使用或计划不当可能会导致性能下降。
索引类型:根据查询模式选择合适的索引类型。Oracle 数据库提供了多种类型的索引,包括 B 树索引、位图索引和函数索引等。例如,B-Tree 索引是 Oracle 中最常用的索引类型,实用于大多数查询场景,尤其是等值查询和范围查询。假设我们有一个员工表 CREATE TABLE employees (emp_id NUMBER PRIMARY KEY, name VARCHAR2(100), department_id NUMBER);,在 department_id 上创建 B-Tree 索引可以使用 CREATE INDEX idx_department ON employees(department_id);。位图索引特别实用于那些有限且重复值多的列(低基数),比如性别、部门等。例如,继续使用 employees 表,在性别字段上创建位图索引可以使用 CREATE BITMAP INDEX idx_gender ON employees(gender);。当常常须要对某个列进行函数操纵后查询时,可以考虑创建函数索引。比如假设常常须要对员工的入职日期进行年份查询,可以使用 CREATE INDEX idx_hire_year ON employees(EXTRACT(YEAR FROM hire_date));。
复合索引:对于常常同时查询多个列的查询,可以创建复合索引。复合索引是基于多个列的索引,可以镌汰查询时须要访问的数据块数量,从而提高查询性能。例如创建一个联合索引可以使用 CREATE INDEX idx_dept_id_name ON employees(department_id, name);。
覆盖索引:当一个索引包含了查询中全部须要的列时,这个索引就是覆盖索引。使用覆盖索引可以制止访问表数据,从而提高查询效率。例如假设查询通常须要员工的 ID 和姓名,可以创建索引 CREATE INDEX idx_emp_id_name ON employees(emp_id, name);。
联合索引的列顺序:在创建联合索引时,列的顺序非常关键。Oracle 会从左到右使用索引中的列。例如创建联合索引 CREATE INDEX idx_dept_id_name ON employees(department_id, name);,假如查询条件包含这两个字段,那么此索引非常有效。
索引压缩:在有重复值较多的列上,使用索引压缩可以节流存储空间。例如对联合索引使用压缩可以使用 CREATE INDEX idx_dept_id_name_compress ON employees(department_id, name) COMPRESS 1;。
不可见索引:不可见索引对优化器是不可见的,可以用于测试索引对查询性能的影响,而不影响现有的查询。例如创建一个不可见索引可以使用 CREATE INDEX idx_emp_email ON employees(email) INVISIBLE;。
分区索引:当表非常大时,使用分区和分区索引可以显著提高性能。例如创建一个分区表和分区索引可以使用 CREATE TABLE sales (sale_id NUMBER, sale_date DATE) PARTITION BY RANGE (sale_date) (PARTITION p2019 VALUES LESS THAN (TO_DATE(‘2020-01-01’, ‘YYYY-MM-DD’)), PARTITION p2020 VALUES LESS THAN (TO_DATE(‘2021-01-01’, ‘YYYY-MM-DD’))); CREATE INDEX idx_sale_date ON sales(sale_date) LOCAL;。
索引跳跃扫描:当查询条件中包含联合索引的一部分列时,Oracle 可以执行索引跳跃扫描来提高效率。例如假设有联合索引 CREATE INDEX idx_dept_job ON employees(department_id, job_id);,即使查询只包含 job_id,Oracle 也能有效地使用这个索引,如 SELECT * FROM employees WHERE job_id = ‘IT_PROG’;。
创建存储过程:在 Oracle 中,创建存储过程须要使用 CREATE PROCEDURE 语句。例如创建一个简朴的存储过程,它接受两个参数并输出它们的和,可以使用 CREATE OR REPLACE PROCEDURE add_nums( num1 IN NUMBER, num2 IN NUMBER, sum OUT NUMBER) IS BEGIN sum := num1 + num2; END add_nums;。
执行存储过程:在 Oracle 中,执行存储过程须要使用 EXECUTE 或 EXECUTE IMMEDIATE 语句。例如,执行上述示例步调,可以使用如下的语句:DECLARE result NUMBER; BEGIN add_nums(10, 20, result); DBMS_OUTPUT.PUT_LINE('The sum is: ’ || result); END ;。
参数类型:在存储过程中,参数可以是输入参数、输出参数或双向参数。输入参数指定存储过程的输入,输出参数指定存储过程的输出,双向参数既可以进行输入,也可以进行输出。声明参数类型的方法如下:(param_name [IN | OUT | IN OUT] param_type [,…])。例如创建一个包含三个参数的存储过程 my_proc,第一个参数 num 是输入参数,第二个参数 str 是双向参数,第三个参数 cur 是输出参数,可以使用 CREATE OR REPLACE PROCEDURE my_proc ( num IN NUMBER, str IN OUT VARCHAR2, cur OUT SYS_REFCURSOR) IS BEGIN – 逻辑实现 END my_proc;。
游标:游标是一种返回效果集的数据布局,它可以遍历查询效果。游标可以是显式或隐式的,显式游标须要声明一个游标变量,并在代码中打开和关闭它,隐式游标则由 Oracle 主动创建和管理。例如创建一个演示如何使用游标的存储过程,可以使用 CREATE OR REPLACE PROCEDURE get_employee( id_list IN VARCHAR2, emp_cur OUT SYS_REFCURSOR) IS BEGIN OPEN emp_cur FOR ‘SELECT * FROM employees WHERE id IN (’ || id_list || ‘)’; END get_employee;。
PL/SQL 表:PL/SQL 表是一种类似于数组的数据布局,它可以存储一组值。在 Oracle 中,可以在存储过程中声明和使用 PL/SQL 表。例如创建一个名为 my_package 的包,其中声明白一个名为 num_list 的 PL/SQL 表类型和一个使用该类型的存储过程 sum_nums,可以使用 CREATE OR REPLACE PACKAGE my_package IS TYPE num_list IS TABLE OF NUMBER INDEX BY PLS_INTEGER; PROCEDURE sum_nums(nums IN num_list, sum OUT NUMBER); END my_package; CREATE OR REPLACE PACKAGE BODY my_package IS PROCEDURE sum_nums(nums IN num_list, sum OUT NUMBER) IS total NUMBER := 0; BEGIN FOR indx IN 1…nums.COUNT LOOP total := total + nums(indx); END LOOP; sum := total; END sum_nums; END my_package;。
利用触发器对在 scott.emp 表上执行的 DML 操纵进行安全性查抄,只有 scott 用户登录数据库后才能向该表中执行 DML 操纵:
在 scott 用户下创建触发器语句:create or replace trigger tri_dm1 before insert or update or delete on scott.emp begin if user <>‘SCOTT’ then raise_application_error(-20001,‘You don’‘t have access to modify this table.’); end if; end;/。
以 system 用户毗连,并对 emp 表执行 DML 操纵,会触发错误。以 scott 用户毗连,并对 emp 表执行 DML 操纵,可以正常执行。
利用触发器进行表和备份表之间的同步复制:
在 scott 用户下创建 scott.emp 表的复本 employee:conn scott/tiger; create table employee as select * from scott.emp;。
在 scott 用户下创建能实现 scott.emp 和 employee 两表之间同步复制的 DML 触发器:create or replace trigger duplicate_empafter update or insert or delete on scott.emp for each row begin if inserting then insert into employee values (:new.empno,:new.ename,:new.job,:new.mgr,:new.hiredate,:new.sal,:new.comm,:new.deptno); elsif deleting then delete from employee where empno=ld.empno; else update employee set empno=:new.empno,ename=:new.ename,job=:new.job,mgr=:new.mgr,hiredate=:new.hiredate,sal=:new.sal,comm=:new.comm,deptno=:new.deptno where empno=ld.empno; end if; end;/。
建立日志表 emp_log:create table emp_log(who varchar2(30), when date, oper varchar2(10));。
在 emp 表上建立语句级触发器,将对 emp 表执行的操纵记录到 emp_log 表中:create or replace trigger dm1_log after insert or update or delete on scott.emp declare oper emp_log.oper%type; begin if inserting then oper:=‘insert’; elsif deleting then oper:=‘delete’; else oper:=‘update’; end if; insert into emp_log values(user,sysdate,oper); end;/。
create or replace procedure count_proc(detpcode in varchar,num out number)ascot number(5);beginselect count(*) into cot from pat_visit_user where dept_code=detpcode;num:=cot;end;
复制代码
参数 IN 表示输入参数,是参数的默认模式。OUT 表示返回值参数,也就是输出参数。类型可以使用恣意 Oracle 中的正当类型。