Oracle 数据库是由甲骨文(Oracle)公司开发的一款关系型数据库管理系统(RDBMS),在企业级应用领域具有广泛的应用。它具有以下显著特点:
Oracle 数据库广泛应用于金融、电信、政府、医疗、制造业等多个行业,常见的应用场景包括:
useradd oracle
passwd oracle
unzip linuxx64_19c_database.zip
su - oracle
./database/runInstaller
su - root
/oracle/oraInventory/orainstRoot.sh
/oracle/product/19.0.0/dbhome_1/root.sh
Oracle 数据库的主要配置文件包括 init.ora
或 spfile.ora
,以及 tnsnames.ora
等。
-- 修改参数并立即生效
ALTER SYSTEM SET parameter_name = value SCOPE = BOTH;
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = your_host)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
Oracle 数据库是一个逻辑上的概念,由数据文件、控制文件、联机日志文件等物理文件组成。一个 Oracle 数据库可以包含多个表空间。
表空间是 Oracle 数据库的逻辑存储单元,用于组织和管理数据文件。一个数据库可以包含多个表空间,常见的表空间类型有系统表空间(SYSTEM)、用户表空间(USERS)、临时表空间(TEMP)等。
数据文件是物理存储单元,用于存储表空间中的数据。一个表空间可以包含一个或多个数据文件,数据文件以二进制文件的形式存储在磁盘上。
表是数据库中存储数据的基本结构,由行和列组成。每一列定义了数据的属性,具有特定的数据类型。可以通过 SQL 语句创建、修改和删除表。
表中的列也称为字段,用于描述数据的某个特征或属性。每个字段都有一个名称和数据类型,数据类型决定了该字段可以存储的数据范围和格式。
表中的一行数据称为一条记录,包含了各个字段的值。记录是数据库中数据存储和操作的基本单元。
Oracle 数据库支持多种数据类型,常见的数据类型包括:
NUMBER
(可以存储整数和小数)、INTEGER
(整数类型)等,用于存储数值数据。CHAR
(定长字符类型)、VARCHAR2
(变长字符类型)、CLOB
(大字符对象类型)等,用于存储文本数据。DATE
(日期时间类型)、TIMESTAMP
(时间戳类型)等,用于存储日期和时间信息。RAW
(二进制数据类型)、BLOB
(二进制大对象类型)等,用于存储二进制数据。CREATE TABLESPACE tablespace_name
DATAFILE 'datafile_path' SIZE 100M;
DROP TABLESPACE tablespace_name INCLUDING CONTENTS AND DATAFILES;
CREATE USER user_name
IDENTIFIED BY password
DEFAULT TABLESPACE tablespace_name
TEMPORARY TABLESPACE temp_tablespace_name;
GRANT CREATE SESSION, CREATE TABLE TO user_name;
sqlplus user_name/password@service_name
CREATE TABLE table_name (
column1 datatype constraint,
column2 datatype constraint,
...
);
例如:
CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(50) NOT NULL,
emp_age NUMBER,
emp_department VARCHAR2(50)
);
DROP TABLE table_name;
ALTER TABLE table_name ADD column_name datatype;
ALTER TABLE table_name DROP COLUMN column_name;
ALTER TABLE table_name MODIFY column_name new_datatype;
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
例如:
INSERT INTO employees (emp_id, emp_name, emp_age, emp_department) VALUES (1, 'John Doe', 30, 'IT');
SELECT column1, column2, ... FROM table_name WHERE condition;
例如:
SELECT * FROM employees WHERE emp_age > 25;
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
例如:
UPDATE employees SET emp_age = 31 WHERE emp_id = 1;
DELETE FROM table_name WHERE condition;
例如:
DELETE FROM employees WHERE emp_id = 1;
SELECT * FROM table_name ORDER BY column_name [ASC|DESC];
例如:
SELECT * FROM employees ORDER BY emp_age DESC;
ROWNUM
实现分页查询。SELECT * FROM (
SELECT ROWNUM AS rn, t.* FROM (
SELECT * FROM employees WHERE emp_age > 25 ORDER BY emp_age
) t WHERE ROWNUM <= 20
) WHERE rn >= 11;
主键是表中唯一标识每条记录的字段或字段组合,一个表只能有一个主键。主键约束确保主键字段的值唯一且不为空。
CREATE TABLE products (
product_id NUMBER PRIMARY KEY,
product_name VARCHAR2(100)
);
唯一约束确保字段的值唯一,但可以为空。一个表可以有多个唯一约束。
CREATE TABLE customers (
customer_id NUMBER,
customer_email VARCHAR2(100) UNIQUE,
customer_name VARCHAR2(50)
);
非空约束确保字段的值不为空。
CREATE TABLE orders (
order_id NUMBER,
order_date DATE NOT NULL,
order_amount NUMBER(10, 2)
);
外键用于建立两个表之间的关联关系,确保一个表中的字段值必须存在于另一个表的主键字段中。
CREATE TABLE order_items (
item_id NUMBER PRIMARY KEY,
order_id NUMBER,
product_id NUMBER,
quantity NUMBER,
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
SELECT * FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;
SELECT * FROM customers
LEFT JOIN orders ON customers.customer_id = orders.customer_id;
SELECT * FROM orders
RIGHT JOIN customers ON orders.customer_id = customers.customer_id;
SELECT * FROM customers
FULL OUTER JOIN orders ON customers.customer_id = orders.customer_id;
子查询是在一个查询中嵌套另一个查询,子查询可以出现在 WHERE
子句、FROM
子句、SELECT
子句等位置。
WHERE
子句中使用子查询SELECT * FROM employees WHERE emp_salary > (SELECT AVG(emp_salary) FROM employees);
FROM
子句中使用子查询SELECT subquery.avg_salary FROM (SELECT AVG(emp_salary) AS avg_salary FROM employees) subquery;
GROUP BY
子句对数据进行分组。SELECT department, COUNT(*) FROM employees GROUP BY department;
COUNT
、SUM
、AVG
、MAX
、MIN
等。SELECT SUM(emp_salary) FROM employees;
窗口函数可以在查询结果的特定窗口内进行计算,语法如下:
function_name(expression) OVER (
[PARTITION BY partition_expression, ... ]
[ORDER BY sort_expression [ASC|DESC], ... ]
[frame_clause]
)
例如:
SELECT
emp_id,
emp_salary,
AVG(emp_salary) OVER (PARTITION BY department) AS avg_department_salary
FROM employees;
索引可以提高查询的效率,加快数据的检索速度。Oracle 数据库通过索引可以快速定位到符合条件的记录,减少全表扫描的开销。
CREATE INDEX idx_name ON employees (emp_name);
CREATE BITMAP INDEX idx_gender ON employees (emp_gender);
CREATE INDEX idx_upper_name ON employees (UPPER(emp_name));
存储过程是一组预编译的 SQL 语句,可以接受参数并执行一系列操作。存储过程可以提高代码的复用性和执行效率。
CREATE OR REPLACE PROCEDURE get_employees_by_department(
p_department IN VARCHAR2,
p_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_cursor FOR
SELECT * FROM employees WHERE emp_department = p_department;
END;
调用存储过程:
DECLARE
v_cursor SYS_REFCURSOR;
v_emp employees%ROWTYPE;
BEGIN
get_employees_by_department('IT', v_cursor);
LOOP
FETCH v_cursor INTO v_emp;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.emp_name);
END LOOP;
CLOSE v_cursor;
END;
函数是返回一个值的 SQL 代码块,函数可以接受参数并返回一个结果。
CREATE OR REPLACE FUNCTION get_employee_count RETURN NUMBER
IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM employees;
RETURN v_count;
END;
调用函数:
SELECT get_employee_count() FROM DUAL;
事务是一组操作,要么全部成功执行,要么全部回滚。事务具有四个特性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称 ACID 特性。
-- 开始事务
SET TRANSACTION;
-- 执行一系列 SQL 操作
INSERT INTO accounts (account_id, balance) VALUES (1, 1000);
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- 提交事务
COMMIT;
-- 或者回滚事务
ROLLBACK;
在 Oracle 中,事务开始于第一条可执行的 SQL 语句,直到遇到 COMMIT
或 ROLLBACK
语句结束。COMMIT
语句将事务中所做的所有更改永久保存到数据库中,而 ROLLBACK
语句则撤销事务中所做的所有更改。
Oracle 支持两种主要的事务隔离级别:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE USER new_user
IDENTIFIED BY password
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp;
-- 授予基本权限
GRANT CREATE SESSION, CREATE TABLE TO new_user;
-- 授予系统级权限
GRANT ALTER ANY TABLE TO new_user;
-- 授予对象级权限
GRANT SELECT ON employees TO new_user;
REVOKE SELECT ON employees FROM new_user;
DROP USER new_user CASCADE;
CASCADE
选项会删除该用户所拥有的所有对象。
expdp system/password directory=dpump_dir dumpfile=backup.dmp tables=employees
impdp system/password directory=dpump_dir dumpfile=backup.dmp tables=employees
-- 关闭数据库
sqlplus / as sysdba
SHUTDOWN IMMEDIATE;
-- 备份文件
cp /u01/app/oracle/oradata/ORCL/* /backup_location/
-- 启动数据库
STARTUP;
-- 开始备份
ALTER TABLESPACE users BEGIN BACKUP;
-- 备份数据文件
cp /u01/app/oracle/oradata/ORCL/users01.dbf /backup_location/
-- 结束备份
ALTER TABLESPACE users END BACKUP;
rman target /
RESTORE DATABASE;
RECOVER DATABASE;
EXPLAIN PLAN
语句分析查询的执行计划,了解查询是如何访问数据的,是否使用了索引等。EXPLAIN PLAN FOR
SELECT * FROM employees WHERE emp_age > 30;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
SELECT *
,尽量只选择需要的列;避免在 WHERE
子句中对列进行函数运算,以免影响索引的使用。init.ora
或 spfile.ora
中的配置参数,如 SGA_TARGET
(系统全局区大小)、PGA_AGGREGATE_TARGET
(程序全局区大小)等。DBMS_STATS
包来更新表和索引的统计信息,帮助优化器生成更优的执行计划。EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'schema_name', tabname => 'table_name');
视图是一种虚拟表,它并不实际存储数据,而是基于 SQL 查询语句定义的。视图可以简化复杂的查询操作,隐藏数据的复杂性,提高数据的安全性。
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;
例如,创建一个包含员工姓名和部门的视图:
CREATE VIEW employee_department_view AS
SELECT emp_name, emp_department
FROM employees;
可以像使用普通表一样使用视图进行查询操作:
SELECT * FROM employee_department_view;
CREATE OR REPLACE VIEW
语句修改视图的定义。CREATE OR REPLACE VIEW view_name AS
SELECT new_column1, new_column2, ...
FROM table_name
WHERE new_condition;
DROP VIEW
语句删除视图。DROP VIEW view_name;
触发器是一种特殊的存储过程,它会在特定的数据库操作(如 INSERT、UPDATE、DELETE)之前或之后自动执行。触发器可以用于实现数据的完整性约束、日志记录等功能。
CREATE OR REPLACE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON table_name
[FOR EACH ROW]
BEGIN
-- 触发器执行的 SQL 语句
END;
例如,创建一个在插入员工记录后记录日志的触发器:
CREATE OR REPLACE TRIGGER log_employee_insert
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
INSERT INTO employee_log (action, timestamp) VALUES ('INSERT', SYSDATE);
END;
使用 DROP TRIGGER
语句删除触发器:
DROP TRIGGER trigger_name;
分区表是将一个大表按照一定的规则分割成多个较小的子表,这些子表在物理上是分开存储的,但在逻辑上仍然是一个表。分区可以提高查询性能、便于数据管理和维护。
CREATE TABLE employees (
emp_id NUMBER,
emp_name VARCHAR2(50),
hire_date DATE
)
PARTITION BY RANGE (hire_date) (
PARTITION p_2023 VALUES LESS THAN (TO_DATE('01 - 01 - 2024', 'DD - MM - YYYY')),
PARTITION p_2024 VALUES LESS THAN (TO_DATE('01 - 01 - 2025', 'DD - MM - YYYY'))
);
CREATE TABLE employees (
emp_id NUMBER,
emp_name VARCHAR2(50),
region VARCHAR2(50)
)
PARTITION BY LIST (region) (
PARTITION p_north VALUES IN ('North', 'Northeast'),
PARTITION p_south VALUES IN ('South', 'Southeast')
);
CREATE TABLE employees (
emp_id NUMBER,
emp_name VARCHAR2(50)
)
PARTITION BY HASH (emp_id)
PARTITIONS 4;
top
、vmstat
等)查看 Oracle 数据库进程的 CPU 使用率,过高的 CPU 使用率可能表示数据库存在复杂查询或性能瓶颈。iostat
等工具监控磁盘的读写速度、I/O 等待时间等指标,判断磁盘是否成为性能瓶颈。-- 生成 AWR 报告
@?/rdbms/admin/awrrpt.sql
SGA_TARGET
、PGA_AGGREGATE_TARGET
等参数;优化 SQL 语句,避免全表扫描和复杂的嵌套查询;定期维护数据库,如重建索引、收集统计信息等。import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class OracleConnectionExample {
public static void main(String[] args) {
try {
// 加载 Oracle JDBC 驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
// 建立数据库连接
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL", "username", "password");
// 创建 Statement 对象
Statement stmt = conn.createStatement();
// 执行 SQL 查询
ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
// 处理查询结果
while (rs.next()) {
System.out.println(rs.getString("emp_name"));
}
// 关闭资源
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
cx_Oracle
库连接 Oracle 数据库。以下是一个简单的 Python 示例代码:import cx_Oracle
# 建立数据库连接
conn = cx_Oracle.connect('username/password@localhost:1521/ORCL')
# 创建游标对象
cursor = conn.cursor()
# 执行 SQL 查询
cursor.execute("SELECT * FROM employees")
# 获取查询结果
results = cursor.fetchall()
for row in results:
print(row[1])
# 关闭游标和连接
cursor.close()
conn.close()
# 将 Oracle 数据库中的数据导入到 HDFS
sqoop import \
--connect jdbc:oracle:thin:@localhost:1521:ORCL \
--username username \
--password password \
--table employees \
--target-dir /user/hadoop/employees
import org.apache.spark.sql.SparkSession
object OracleSparkIntegration {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
.appName("OracleSparkIntegration")
.master("local[*]")
.getOrCreate()
val jdbcDF = spark.read
.format("jdbc")
.option("url", "jdbc:oracle:thin:@localhost:1521:ORCL")
.option("driver", "oracle.jdbc.driver.OracleDriver")
.option("dbtable", "employees")
.option("user", "username")
.option("password", "password")
.load()
jdbcDF.show()
spark.stop()
}
}