目录
快速了解
Oracle Database,又名 Oracle RDBMS,简称 Oracle。Oracle 数据库系统是美国 Oracle 公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(client/server)或B/S体系结构的数据库之一,比如 SilverStream 就是基于数据库的一种中间件。
- 官方下载地址:技术资源 | Oracle 中国
- 辅助文档:Oracle 12C安装教程_w3cschool
Oracle、SQL Server和MySQL优劣与选择
- Oracle:
- 优点:
- 1. 它被认为是目前最功能强大的数据库之一。
- 2. 具有广泛的可扩展性和高性能特征。
- 缺点:
- 1. Oracle的许可证费用非常高昂,可能是其中最贵的之一。
- 2. Oracle需要专业技能来处理和管理,相对而言学习难度较高。
- SQL Server:
- 优点:
- 1. SQL Server容易维护和管理。
- 2. 它提供了广泛的支持,可以轻松管理和部署应用程序。
- 3. 具有高级安全性特征和内建分析服务。
- 缺点:
- 1. 虽然SQL Server比Oracle的成本低得多,但仍然需要购买授权,所有版本均不允许外部开源的使用。
- 2. SQL Server在高负载环境中处理效率较低,在总体性能方面也稍弱于Oracle。
- MySQL:
- 优点:
- 1. MySQL完全开放源代码。
- 2. MySQL具有简单、直观的用户界面,易于使用。
- 3. 可扩展性良好,深受互联网领域大规模分布的喜爱。
- 缺点:
- 1. 相比于Oracle和SQL Server,MySQL缺少一些企业级功能。
- 2. MySQL在支持分布式的方面需要额外的定制和工程技能。
- 总体上来说,选择数据库应该取决于您的需求、成本预算和可得到的技术资源。如果你需要高性能和广泛的支持,那么Oracle或SQL Server可能更适合你。如果你需要一个低成本的、容易使用的解决方案,则MySQL可能是一个明智的选择。
查看是否开启oracle服务
- 在Windows系统上,可以通过以下步骤检查本地是否已启动Oracle服务:
- 打开“服务”管理器:
- 在键盘上按下Win + R键,打开运行对话框。
- 输入services.msc并点击“确定”按钮。
- 在“服务”管理器窗口中,找到Oracle相关的服务:
- 滚动或使用搜索功能查找与Oracle相关的服务。通常,Oracle服务的名称以"Oracle"开头。
- 常见的Oracle服务名称包括"OracleServiceXE"、"OracleServiceORCL"等,具体名称取决于你的Oracle安装和配置。
- 检查服务状态:
- 查看Oracle服务的状态列。如果服务运行正常,状态将显示为"正在运行"、"已启动"或"自动"。
- 如果服务未启动,状态将显示为"已停止"、"未启动"或"手动"。
- 如果Oracle服务处于停止状态,可以右键点击该服务并选择“启动”选项来启动它。如果服务是手动启动的,也可以通过右键点击选择“自动”选项,使其在系统启动时自动启动。
- 对于Linux系统,可以使用以下命令来检查Oracle服务的运行状态:
- sudo systemctl status oracle-xe
- 上述命令将显示Oracle服务的状态信息,包括是否正在运行和最近的日志记录。
- 执行上述操作建议使用管理员或超级用户权限。
常用终端命令
- 查看oracle客户端版本命令:sqlplus -v
- 1. `sqlplus` 命令:这是 Oracle 的命令行界面工具,用于连接到数据库并执行 SQL 命令。
- - 语法:sqlplus username/password@connect_identifier
- connect_identifier 是数据库连接标识符(通常是主机名、端口和服务名/ SID)
- - 示例:`sqlplus scott/tiger@localhost:1521/orcl`
- 2. `CONNECT` 命令:用于连接到数据库。
- - 语法:CONNECT username/password@connect_identifier
- - 示例:`CONNECT scott/tiger@orcl`
- 3. `CREATE USER` 命令:创建新用户。
- - 语法:CREATE USER username IDENTIFIED BY password;
- - 示例:`CREATE USER new_user IDENTIFIED BY password;`
- 4. `GRANT` 命令:授予用户权限。
- - 语法:GRANT privilege_name TO username;
- - 示例:`GRANT SELECT, INSERT, UPDATE ON table_name TO new_user;`
- 5. `REVOKE` 命令:撤销用户权限。
- - 语法:REVOKE privilege_name FROM username;
- - 示例:`REVOKE SELECT, INSERT, UPDATE ON table_name FROM new_user;`
- 6. `ALTER USER` 命令:更改用户密码。
- - 语法:ALTER USER username IDENTIFIED BY new_password;
- - 示例:`ALTER USER new_user IDENTIFIED BY new_password;`
- 7. lsnrctl:监听控制工具,用于启动、停止和管理 Oracle 监听器。
- 示例:lsnrctl start(启动监听器)、lsnrctl stop(停止监听器)
- 语法:lsnrctl command
- tnsping:用于测试与远程 Oracle 数据库服务器的网络连接是否正常。
- 语法:tnsping connect_identifier
- 示例:tnsping orcl
- sqlldr:用于将数据从平面文件加载到 Oracle 数据库表中。
- 语法:sqlldr username/password@connect_identifier control=control_file
- 示例:sqlldr scott/tiger@orcl control=data.ctl
- expdp 和 impdp:用于导出和导入 Oracle 数据库中的数据和对象。
- 语法:expdp username/password@connect_identifier DIRECTORY=directory_name DUMPFILE=dumpfile_name impdp username/password@connect_identifier DIRECTORY=directory_name DUMPFILE=dumpfile_name
- 示例:expdp scott/tiger@orcl DIRECTORY=dpump_dir DUMPFILE=expdp_scott.dmp impdp scott/tiger@orcl DIRECTORY=dpump_dir DUMPFILE=expdp_scott.dmp
- sqlplus /nolog:启动 sqlplus 但不自动登录到数据库,可以在启动后手动输入连接命令。
- 语法:sqlplus /nolog
- 示例:sqlplus /nolog(启动 sqlplus)、CONNECT scott/tiger@orcl(手动连接)
常用数据类型
数据类型 内存空间大小 优化建议 CHAR 固定长度(最大 2000 字节) - 避免过度使用 CHAR 类型,除非存储的数据确实是固定长度的。
- 选择合适的长度,避免过度分配空间。
- 对于经常变化长度的数据,考虑使用 VARCHAR2 类型。
VARCHAR2 可变长度(最大 4000 字节) - 对于变长字符串,使用 VARCHAR2 而不是 CHAR 类型可节省空间。
- 根据实际需求选择合适的长度,避免过度分配空间。
- 对于较大的字符串,考虑使用 CLOB 数据类型。
NUMBER 根据定义的精度和范围变化 - 选择合适的精度和范围,避免过度分配空间。
- 对于整数类型数据,考虑使用具体的整数类型(如 SMALLINT、INTEGER、BIGINT),以便更好地利用空间。
- 对于小数类型数据,根据实际需求选择合适的精度和范围。
- 避免在数据库中存储过多不需要的小数位数。
DATE 7 字节 - 在需要存储日期和时间的字段时使用 DATE 类型。
- 避免在日期字段中存储无关的时间信息。
- 使用日期函数和索引来提高查询性能。
- 考虑使用 TIMESTAMP 类型来存储更精确的时间信息。
TIMESTAMP 11 字节到 20 字节(取决于精度) - 根据实际需求选择合适的精度。
- 避免使用不必要的精度,以节省空间。
- 使用日期和时间函数来处理 TIMESTAMP 数据类型。
- 考虑使用 TIMEZONE 类型来存储具有时区信息的时间戳。
- 考虑使用时间戳列来存储时间序列数据。
CLOB 根据存储的字符数变化 - 使用 CLOB 类型来存储较大的文本数据。
- 避免在 CLOB 列上执行频繁的更新操作,因为更新需要更多的资源和时间。
- 对于只读或很少更改的文本数据,考虑使用 BLOB 类型来存储以提高性能。
- 对于较小的文本数据,使用 VARCHAR2 类型可能更合适。
BLOB 根据存储的字节数变化 - 使用 BLOB 类型来存储二进制数据(如图像、音频、视频等)。
- 避免在 BLOB 列上执行频繁的更新操作,因为更新需要更多的资源和时间。
- 对于只读或很少更改的二进制数据,考虑使用 CLOB 类型来存储以提高性能。
- 对于较小的二进制数据,考虑使用 RAW 或 VARCHAR2 类型。
BOOLEAN 1 字节 - 使用 BOOLEAN 类型来存储布尔值。
- 避免在数据库中存储大量的布尔字段,因为每个字段都会占用额外的存储空间。
- 使用约束和索引来优化布尔字段的查询性能。
RAW 可变长度(最大 2000 字节) - 使用 RAW 类型来存储原始二进制数据。
- 根据实际需求选择合适的长度,避免过度分配空间。
- 对于较大的二进制数据,考虑使用 BLOB 类型。
- 避免在 RAW 列上执行频繁的更新操作,因为更新需要更多的资源和时间。
根据实际需求和数据特性,选择合适的数据类型和长度可以有效地优化数据库的存储和性能。另外,在设计数据库时,还需要考虑适当的索引、分区和数据压缩等策略来进一步优化性能。
常用运算符
与mysql无大差异,故不赘述。但有些独有的
1. (+) 运算符:用于实现外连接(Outer Join),特别是在早期版本的 Oracle 中使用。它可以在两个表之间创建一个左外连接或右外连接。
2. || 运算符:用于字符串连接,与标准的 ANSI SQL 中的字符串连接运算符不同,Oracle 使用两个竖线(||)来表示字符串连接。
3. PRIOR 运算符:用于处理递归查询(Recursive Query),可以在查询中引用自身。
4. ROWID 运算符(或者说伪列):用于访问行的物理地址,每个行都有一个唯一的 ROWID 值,可以使用该运算符来访问特定的行。
5. ROWNUM (或者说伪列)运算符:用于限制结果集的行数,可以使用 ROWNUM 运算符来获取前 N 行或进行分
DDL
- -- 创建数据库
CREATE DATABASE mydatabase;
- -- 切换到新创建的数据库
ALTER SESSION SET CONTAINER = mydatabase;
- -- 创建表空间
CREATE TABLESPACE mytablespace DATAFILE '/path/to/datafile.dbf' SIZE 100M AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED DEFAULT STORAGE (INITIAL 10M NEXT 10M) EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
创建了名为 mytablespace 的表空间,将数据文件存储在 /path/to/datafile.dbf,初始大小为100MB,自动扩展50MB,最大大小不限制。使用默认存储属性,启用局部管理和自动段空间管理。
参数说明
参数 描述 TABLESPACE_NAME 表空间的名称 DATAFILE 表空间的数据文件路径和名称 SIZE 表空间的初始大小 AUTOEXTEND 指示是否自动扩展表空间 NEXT 自动扩展时的增量大小 MAXSIZE 表空间的最大大小 REUSE 指示是否重用现有的数据文件 DEFAULT STORAGE 表空间的默认存储参数 EXTENT MANAGEMENT 表空间的扩展管理方式 SEGMENT SPACE MANAGEMENT 表空间的段空间管理方式 LOGGING 指示是否启用表空间的日志记录 FORCE LOGGING 指示是否强制表空间的日志记录 BLOCKSIZE 表空间的块大小 DICTIONARY 指示是否创建数据字典表空间 ONLINE 指示是否在线创建表空间 ENCRYPTION 指示是否对表空间进行加密 COMPRESS 指示是否对表空间进行压缩 RETENTION 表空间的数据保留期限 FLASHBACK ON 指示是否启用表空间的闪回功能 BLOCKS 表空间的块数 - --创建表
- 与sql server没有太大区别,语法:
CREATE TABLE table_name ( column1 datatype constraint, column2 datatype constraint, ... constraint );
公司项目推荐写法
-- 判?表是否存在 DECLARE table_exists NUMBER; BEGIN SELECT COUNT(*) INTO table_exists FROM user_tables WHERE table_name = 'book'; IF table_exists > 0 THEN -- 表已存在,?行其他操作或?? DBMS_OUTPUT.PUT_LINE('表已存在'); ELSE -- 表不存在,?建表 EXECUTE IMMEDIATE ' CREATE TABLE book ( bookId NUMBER(20) GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY, bookName VARCHAR2(100) NOT NULL, authorId Number(20) NOT NULL, cateId Number(20) NOT NULL, createDate date not null, updateDate date not null, price decimal(10,2) not null, isVip Number(1,0) not null )'; -- 添加表注? EXECUTE IMMEDIATE 'COMMENT ON TABLE book IS ''?籍表'''; -- 添加列注? EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.bookId IS ''?籍ID'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.bookName IS ''?籍名?'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.authorId IS ''作者ID'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.cateId IS ''分?ID'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.createDate IS ''?建日期'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.price IS ''价格'''; EXECUTE IMMEDIATE 'COMMENT ON COLUMN book.isVip IS ''是否vip?物'''; DBMS_OUTPUT.PUT_LINE('表已?建并?置完?'); END IF; END;
- --查看表描述
describe book;
- --删除表
- TRUNCATE table 表名; 截断表数据不会删除表结构,并会保存包括表的结构、数据、约束、索引和自增id起始值等信息。
- drop table 表名;删除表结构
- alter 建立约束
- 基本语法:alter table table_name add constraint 约束名 约束内容;
- 添加主键约束 ALTER TABLE 表名 ADD CONSTRAINT 约束名 PRIMARY KEY(列名1[,列名2...]);
- 添加外键约束 ALTER TABLE 主表名 ADD CONSTRAINT 约束名 FOREIGN KEY(列名1[,列2...]) REFERENCES 从表名(列名1[,列名2...]);
- 添加check约束 ALTER TABLE 表名 ADD CONSTRAINT 约束名 CHECK(条件);
- 添加唯一约束 ALTER TABLE 表名 ADD CONSTRAINT 约束名 UNIQUE(列名);
- 删除约束ALTER TABLE 表名 DROP CONSTRAINT 约束名;
- 添加非空约束 ALTER TABLE 表名 MODIFY 列名 NOT NULL;
- alter 修改表内容
- 修改列名 alter table table_name rename column old_row_name to new_row_name;
- 修改列类型 alter table table_name modify row_name datatype;
- 添加列 alter table table_name add row_name datatype;
- 修改表名 alter table table_name rename to new_table_name;
- 删除列 alter table table_name drop column row_name;
DML
- 增删改:
- 与mysql一致,but !!!,
- insert into语句中与mysql不同,values后面不能直接接多个赋值块。
- 时间类型需要使用 TO_DATE('1999-05-02', 'YYYY-MM-DD')函数转换
- 切記:在Oracle大部分工具中,比如SQL Developer 中,DML語句需要加上commit關鍵字才能提交事務,或者使用工具自帶提交按鈕提交
DQL
与mysql没啥区别,就是用于分页的关键字是rownum,
语法:
SELECT * FROM ( SELECT column1, column2, ROWNUM AS rn FROM table_name WHERE condition ORDER BY column1 ) WHERE rn BETWEEN start_row AND end_row;
示例
select* from (select b.*,rownum as rn from book b order by bookid) where rn between 5 and 10;
特殊关键字
- distinct --去重
- union --并集,去重
- union all --并集,不去重。性能最好
- minus --补集
- intersect --交集
特殊关键字 描述 示例 DISTINCT 用于返回唯一的结果集 SELECT DISTINCT column1, column2 FROM table_name; UNION 用于合并两个或多个查询结果集,并去重 SELECT column1 FROM table_name1 UNION SELECT column1 FROM table_name2; UNION ALL 用于合并两个或多个查询结果集,并保留全部数据 SELECT column1 FROM table_name1 UNION ALL SELECT column1 FROM table_name2; MINUS 用于从第一个查询结果集中减去第二个查询结果集 SELECT column1 FROM table_name1 MINUS SELECT column1 FROM table_name2; INTERSECT 用于返回两个查询结果集的交集 SELECT column1 FROM table_name1 INTERSECT SELECT column1 FROM table_name2;
函数
字符函数(Character Functions):
函数 说明 示例 LENGTH 返回字符串的字符数 SELECT LENGTH(last_name) FROM employees; UPPER 将字符串转换为大写 SELECT UPPER(first_name) FROM employees; LOWER 将字符串转换为小写 SELECT LOWER(last_name) FROM employees; SUBSTR 提取字符串的子串 SELECT SUBSTR(first_name, 1, 3) FROM employees; CONCAT 连接两个字符串 SELECT CONCAT(first_name, ' ', last_name) FROM employees; 数值函数(Numeric Functions):
函数 说明 示例 ROUND 四舍五入 SELECT ROUND(salary, 2) FROM employees; TRUNC 截断小数部分 SELECT TRUNC(salary, 0) FROM employees; ABS 返回绝对值 SELECT ABS(salary) FROM employees; MOD 返回除法的余数 SELECT MOD(employee_id, 10) FROM employees; CEIL 返回不小于指定数的最小整数 SELECT CEIL(salary) FROM employees; 日期函数(Date Functions):
函数 说明 示例 SYSDATE 返回当前日期和时间 SELECT SYSDATE FROM dual; TO_CHAR 将日期转换为字符串 SELECT TO_CHAR(hire_date, 'YYYY-MM-DD') FROM employees; MONTHS_BETWEEN 计算两个日期之间的月数差 SELECT MONTHS_BETWEEN(hire_date, SYSDATE) FROM employees; ADD_MONTHS 在日期上增加指定的月数 SELECT ADD_MONTHS(hire_date, 6) FROM employees; TRUNC 截断日期的部分 SELECT TRUNC(hire_date, 'MM') FROM employees; 聚合函数(Aggregate Functions):
函数 说明 示例 SUM 计算指定列的总和 SELECT SUM(salary) FROM employees; AVG 计算指定列的平均值 SELECT AVG(salary) FROM employees; COUNT 计算指定列的行数 SELECT COUNT(*) FROM employees; MAX 获取指定列的最大值 SELECT MAX(salary) FROM employees; MIN 获取指定列的最小值 SELECT MIN(salary) FROM employees; 日期函数(Date Functions):
函数 说明 示例 SYSDATE 返回当前日期和时间 SELECT SYSDATE FROM dual; TO_CHAR 将日期转换为字符串 SELECT TO_CHAR(hire_date, 'YYYY-MM-DD') FROM employees; MONTHS_BETWEEN 计算两个日期之间的月数差 SELECT MONTHS_BETWEEN(hire_date, SYSDATE) FROM employees; ADD_MONTHS 在日期上增加指定的月数 SELECT ADD_MONTHS(hire_date, 6) FROM employees; TRUNC 截断日期的部分 SELECT TRUNC(hire_date, 'MM') FROM employees; EXTRACT 提取日期的部分(如年、月、日、时、分、秒等) SELECT EXTRACT(YEAR FROM hire_date) FROM employees; 判断函数(Conditional Functions):
函数 说明 示例 CASE 条件判断函数,用于执行多个条件的选择逻辑 SELECT employee_id, salary, CASE WHEN salary > 5000 THEN 'High' WHEN salary > 3000 THEN 'Medium' ELSE 'Low' END FROM employees; DECODE 类似于CASE函数,用于执行多个条件的选择逻辑 SELECT employee_id, salary, DECODE(salary, 5000, 'High', 3000, 'Medium', 'Low') FROM employees; NVL 如果表达式为空,则返回指定的替代值 SELECT employee_id, salary, NVL(commission_pct, 0) FROM employees; NULLIF 如果两个表达式相等,则返回NULL SELECT employee_id, salary, NULLIF(commission_pct, 0) FROM employees; COALESCE 返回参数列表中第一个非空表达式的值 SELECT employee_id, salary, COALESCE(commission_pct, 0) FROM employees;
PL/SQL
PL/SQL(Procedural Language/Structured Query Language)是Oracle数据库的一种编程语言,用于编写存储过程、触发器、函数和包等数据库对象。它结合了SQL语句的数据操作能力和常规编程语言的流程控制能力,提供了丰富的语法和功能,用于构建复杂的数据库应用程序。
特点和优势
- 紧密集成的数据库访问:PL/SQL是Oracle数据库的一部分,可以直接访问和操作数据库中的数据,无需通过外部接口或API。
- 高性能:PL/SQL通过减少与数据库的通信次数和减轻网络负载,提高了性能。
- 程序化逻辑:PL/SQL具有常规编程语言的特性,如条件语句、循环语句和异常处理,可以实现复杂的业务逻辑。
- 代码重用和封装:PL/SQL支持封装和模块化编程,可以将相关的代码组合成过程、函数和包,提高了代码的可读性和可维护性。
- 安全性:PL/SQL提供了对数据库对象的访问控制,可以限制用户对数据库的操作权限,确保数据安全性和完整性。
PL/SQL语法和结构
PL/SQL的语法和结构类似于其他编程语言,它由块(Block)、过程(Procedure)、函数(Function)、触发器(Trigger)和包(Package)等组成。
一个PL/SQL块的基本结构如下:
DECLARE -- 声明变量和常量 BEGIN -- 执行语句块 EXCEPTION -- 异常处理 END; /
在PL/SQL块中,可以使用DECLARE部分声明变量和常量,使用BEGIN和END包围执行语句块。EXCEPTION部分用于处理异常情况。
以下是一个简单的PL/SQL块示例:
DECLARE v_name VARCHAR2(100); BEGIN v_name := 'John'; DBMS_OUTPUT.PUT_LINE('Hello, ' || v_name); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('An error occurred'); END; /
存储过程(Procedure):存储过程是一组预先编译的SQL语句和PL/SQL代码,可以由应用程序或其他数据库对象调用。存储过程可以接收参数并执行数据操作,可以包含条件语句、循环语句和异常处理等。存储过程可以通过CREATE PROCEDURE语句创建,使用CALL语句调用。
函数(Function):函数是一种特殊的存储过程,它返回一个值。函数可以接收参数并返回一个结果,可以嵌套调用。函数可以通过CREATE FUNCTION语句创建,通过SELECT语句或PL/SQL代码调用。
触发器(Trigger):触发器是与表相关联的PL/SQL代码,当特定的数据库事件(如INSERT、UPDATE或DELETE)发生时自动触发执行。触发器可以在数据操作之前或之后执行,常用于实现数据约束、审计跟踪和业务逻辑。触发器可以通过CREATE TRIGGER语句创建。
异常处理
PL/SQL提供了异常处理机制,用于捕获和处理运行时错误。可以使用EXCEPTION部分来定义异常处理程序,并指定对应的异常类型和处理逻辑。
以下是一个简单的异常处理示例:
DECLARE v_num1 NUMBER := 10; v_num2 NUMBER := 0; BEGIN DBMS_OUTPUT.PUT_LINE(v_num1/v_num2); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Cannot divide by zero'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('An error occurred'); END; /
包(Package)
包(Package)是PL/SQL中的一个重要概念,它是一个逻辑单元,用于封装相关的存储过程、函数、变量和常量等。通过创建包,可以将相关的代码组织成逻辑单元,并提供访问控制和封装性。
以下是一个简单的包的示例:
CREATE OR REPLACE PACKAGE my_package IS PROCEDURE procedure1; FUNCTION function1 RETURN NUMBER; CONSTANT constant1 CONSTANT NUMBER := 10; END my_package; / CREATE OR REPLACE PACKAGE BODY my_package IS PROCEDURE procedure1 IS BEGIN DBMS_OUTPUT.PUT_LINE('This is procedure1'); END; FUNCTION function1 RETURN NUMBER IS BEGIN RETURN constant1; END; END my_package; /
存储过程高级
1.游标(Cursor)和游标变量:游标用于查询结果集,并通过游标变量进行操作。可以使用循环语句和条件来处理游标的结果,并进行数据操作。
CREATE OR REPLACE PROCEDURE process_employees IS CURSOR c_employees IS SELECT employee_id, first_name, last_name FROM employees; v_id employees.employee_id%TYPE; v_first_name employees.first_name%TYPE; v_last_name employees.last_name%TYPE; BEGIN OPEN c_employees; LOOP FETCH c_employees INTO v_id, v_first_name, v_last_name; EXIT WHEN c_employees%NOTFOUND; -- 处理每一条记录 -- ... END LOOP; CLOSE c_employees; END; /
上面的例子中,通过游标c_employees查询employees表的记录,并通过循环语句处理每一条记录。
2.异常处理和事务控制:存储过程可以包含异常处理部分,在发生错误时执行特定的逻辑。同时,可以使用事务控制语句(BEGIN、COMMIT、ROLLBACK)来确保数据的一致性和完整性。
CREATE OR REPLACE PROCEDURE transfer_funds( p_from_account_id IN accounts.account_id%TYPE, p_to_account_id IN accounts.account_id%TYPE, p_amount IN accounts.balance%TYPE) IS v_balance accounts.balance%TYPE; BEGIN -- 检查源账户余额是否足够 SELECT balance INTO v_balance FROM accounts WHERE account_id = p_from_account_id; IF v_balance < p_amount THEN RAISE_APPLICATION_ERROR(-20001, 'Insufficient funds'); END IF; -- 扣除源账户余额 UPDATE accounts SET balance = balance - p_amount WHERE account_id = p_from_account_id; -- 增加目标账户余额 UPDATE accounts SET balance = balance + p_amount WHERE account_id = p_to_account_id; COMMIT; -- 提交事务 EXCEPTION WHEN OTHERS THEN ROLLBACK; -- 回滚事务 RAISE; -- 重新抛出异常 END; /
上面的例子中,创建了一个名为transfer_funds的存储过程,用于在两个账户之间转移资金。在过程中,需要使用异常处理来处理错误情况,并使用事务控制来保证数据的一致性。
3.动态SQL:存储过程可以使用动态SQL语句,根据不同的条件构建和执行SQL语句。
CREATE OR REPLACE PROCEDURE search_employees( p_department_id IN departments.department_id%TYPE, p_job_id IN employees.job_id%TYPE) IS v_sql VARCHAR2(200); v_cursor SYS_REFCURSOR; BEGIN v_sql := 'SELECT employee_id, first_name, last_name FROM employees WHERE 1 = 1'; IF p_department_id IS NOT NULL THEN v_sql := v_sql || ' AND department_id = ' || p_department_id; END IF; IF p_job_id IS NOT NULL THEN v_sql := v_sql || ' AND job_id = ''' || p_job_id || ''''; END IF; OPEN v_cursor FOR v_sql; -- 处理结果集 -- ... CLOSE v_cursor; END; /
上面的例子中,创建了一个名为search_employees的存储过程,根据不同的条件构建动态SQL语句,并使用游标处理查询结果集。
数据同步
全量同步数据的方法:
1.使用INSERT INTO SELECT语句:使用INSERT INTO SELECT语句从源表中选取所有数据插入到目标表中。
INSERT INTO target_table (column1, column2, ...) SELECT column1, column2, ... FROM source_table;
2.使用MERGE语句:使用MERGE语句将源表的数据合并到目标表中,如果记录存在则更新,如果不存在则插入。
MERGE INTO target_table t USING source_table s ON (t.primary_key = s.primary_key) WHEN MATCHED THEN UPDATE SET t.column1 = s.column1, t.column2 = s.column2 WHEN NOT MATCHED THEN INSERT (column1, column2, ...) VALUES (s.column1, s.column2, ...);
3.使用数据泵工具:使用Oracle的数据泵工具(如expdp和impdp)导出源表的数据,然后再导入到目标表中。
expdp schema_name.table_name directory=dpump_dir dumpfile=data.dmp logfile=expdp.log
impdp schema_name.table_name directory=dpump_dir dumpfile=data.dmp logfile=impdp.log
增量同步数据的方法:
- 使用触发器(Trigger):创建一个触发器,在源表上触发INSERT、UPDATE或DELETE操作时,将相应的数据同步到目标表中。
CREATE OR REPLACE TRIGGER sync_trigger AFTER INSERT OR UPDATE OR DELETE ON source_table FOR EACH ROW BEGIN -- 同步数据到目标表 -- INSERT, UPDATE, DELETE, etc. END;
- 使用存储过程(Procedure):创建一个存储过程,通过查询源表的增量数据,然后将其同步到目标表中。
CREATE OR REPLACE PROCEDURE incremental_sync AS BEGIN -- 查询增量数据并进行同步 -- INSERT, UPDATE, DELETE, etc. COMMIT; -- 提交事务 END;
- 使用物化视图(Materialized View):创建一个物化视图,该视图根据定义的刷新条件定期从源表中选择增量数据,并将其存储在目标表中。
CREATE MATERIALIZED VIEW mv_sync REFRESH FAST ON COMMIT AS SELECT column1, column2, ... FROM source_table WHERE last_modified > sysdate - 1;