在企业级数据分析场景中,Oracle 数据库作为常用的关系型数据库,存储着海量核心业务数据。本文将手把手教你用 Python 连接 Oracle 数据库,实现数据读取、多维度数据探查(缺失值、异常值、分布特征、相关性)与可视化分析,代码精简易上手,无需复杂配置,助力快速挖掘 Oracle 数据价值。

一、核心原理与环境准备

1. 核心逻辑

Python 操作 Oracle 数据库进行数据分析的核心流程:

关键工具说明:

  • cx_Oracle:Python 连接 Oracle 数据库的核心库,支持 SQL 执行、数据读取;
  • pandas:数据处理核心库,将查询结果转换为 DataFrame,便于探查与分析;
  • matplotlib/seaborn:数据可视化库,直观呈现数据特征;
  • 优势:无需导出 Oracle 数据为 CSV,直接联动分析,实时性强、效率高。

2. 环境准备

工具 / 依赖

版本要求

作用描述

Python

3.7+

核心运行环境

cx_Oracle

8.0+

Oracle 数据库连接核心库

pandas

1.0+

数据处理与 DataFrame 转换

matplotlib/seaborn

3.0+/0.10+

数据可视化

numpy

1.18+

数值计算支持

Oracle Instant Client

12c+/19c+

Oracle 客户端(需与数据库版本兼容)

pip

20.0+

Python 包管理工具

3. 依赖安装与环境配置

(1)安装 Python 依赖

打开终端执行以下命令,安装核心库:


pip install cx_Oracle pandas matplotlib seaborn numpy

(2)Oracle 客户端配置(关键步骤)
  1. 下载 Oracle Instant Client(轻量客户端):

官网地址:https://www.oracle.com/database/technologies/instant-client/downloads.html

选择与操作系统匹配的版本(如 Windows 64 位、Linux 64 位),无需安装,解压即可;

  1. 配置环境变量:
    • Windows:将解压后的客户端路径(如D:\instantclient_19_19)添加到系统环境变量PATH;
    • Linux/Mac:执行export LD_LIBRARY_PATH=~/instantclient_19_19:$LD_LIBRARY_PATH(临时生效),或写入~/.bashrc永久生效;
  1. 验证配置:终端执行sqlplus,若未报错则配置成功。

4. 数据集说明

以 Oracle 数据库中销售业务表(SALES_DATA) 为例,表结构如下(实际场景替换为目标表):

字段名

字段类型

说明

SALE_ID

NUMBER(10)

销售订单 ID(主键)

SALE_DATE

DATE

销售日期

REGION

VARCHAR2(50)

销售地区

PRODUCT_TYPE

VARCHAR2(50)

产品类型

SALE_AMOUNT

NUMBER(12,2)

销售金额(元)

QUANTITY

NUMBER(8)

销售数量(件)

CUSTOMER_TYPE

VARCHAR2(20)

客户类型(个人 / 企业)

二、核心代码实现:Python 连接 Oracle 数据库

1. 数据库连接与数据读取


import cx_Oracle

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns

import numpy as np

from datetime import datetime

# 设置中文字体(避免中文乱码)

plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统

# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # Mac系统

plt.rcParams['axes.unicode_minus'] = False

def oracle_connect(query_sql, db_config):

"""

连接Oracle数据库并执行SQL查询

:param query_sql: 待执行的SQL查询语句

:param db_config: 数据库配置字典(包含user/password/dsn)

:return: 查询结果(DataFrame)

"""

try:

# 1. 连接数据库

conn = cx_Oracle.connect(

user=db_config['user'],

password=db_config['password'],

dsn=db_config['dsn'] # DSN格式:主机名:端口号/服务名(如:127.0.0.1:1521/ORCL)

)

print("Oracle数据库连接成功!")

# 2. 执行SQL查询并转换为DataFrame

df = pd.read_sql(query_sql, conn)

# 3. 关闭连接

conn.close()

print(f"数据读取成功,共获取 {len(df)} 条记录,{len(df.columns)} 个字段")

return df

except cx_Oracle.Error as e:

print(f"Oracle数据库连接/查询失败:{e}")

return None

# -------------------------- 数据库配置(需手动修改)--------------------------

db_config = {

'user': '你的Oracle用户名', # 如:SCOTT

'password': '你的Oracle密码', # 如:TIGER

'dsn': '主机IP:端口号/服务名' # 如:192.168.1.100:1521/ORCL

}

# -------------------------- SQL查询语句(按需修改)--------------------------

# 读取销售表所有数据(可添加WHERE条件筛选目标数据)

query_sql = """

SELECT SALE_ID, SALE_DATE, REGION, PRODUCT_TYPE, SALE_AMOUNT, QUANTITY, CUSTOMER_TYPE

FROM SALES_DATA

-- WHERE SALE_DATE BETWEEN TO_DATE('2024-01-01', 'YYYY-MM-DD') AND TO_DATE('2024-12-31', 'YYYY-MM-DD')

"""

# 执行数据读取

df = oracle_connect(query_sql, db_config)

# 查看数据基本信息

if df is not None:

print("\n数据预览(前5行):")

print(df.head())

print("\n数据字段信息:")

print(df.info())

2. 代码解析(关键步骤)

(1)数据库配置
  • user/password:Oracle 数据库的登录用户名和密码;
  • dsn:数据库连接串,格式为主机IP:端口号/服务名(默认端口 1521,服务名通常为 ORCL 或 XE)。
(2)数据读取逻辑
  • 用cx_Oracle.connect建立数据库连接,pd.read_sql直接执行 SQL 并转换为 DataFrame(无需手动处理结果集);
  • 支持复杂 SQL 查询(如 WHERE 筛选、GROUP BY 聚合、JOIN 关联查询),灵活获取目标数据;
  • 读取后立即关闭连接,避免资源占用。
(3)数据预处理(可选)

# 数据预处理:转换日期格式、处理缺失值

if df is not None:

# 转换日期字段(SALE_DATE)为datetime类型

df['SALE_DATE'] = pd.to_datetime(df['SALE_DATE'])

# 处理缺失值(示例:删除关键字段缺失的记录)

df = df.dropna(subset=['SALE_AMOUNT', 'QUANTITY', 'REGION'])

# 新增衍生字段(如:单价)

df['UNIT_PRICE'] = df['SALE_AMOUNT'] / df['QUANTITY'].round(2)

print("\n预处理后数据预览:")

print(df.head())

三、多维度数据探查(核心分析步骤)

数据探查是数据分析的基础,重点关注缺失值、异常值、分布特征、分类变量占比、数值变量相关性等维度:

1. 维度 1:缺失值探查


def missing_value_analysis(df):

"""缺失值探查与可视化"""

# 计算各字段缺失值占比

missing_info = df.isnull().sum() / len(df) * 100

missing_info = missing_info[missing_info > 0].sort_values(ascending=False)

if len(missing_info) > 0:

print("\n=== 缺失值探查结果 ===")

print(missing_info.round(2).map(lambda x: f"{x}%"))

# 可视化缺失值

plt.figure(figsize=(10, 6))

sns.barplot(x=missing_info.index, y=missing_info.values, color='#E74C3C', alpha=0.7)

plt.title('各字段缺失值占比', fontsize=14, fontweight='bold')

plt.xlabel('字段名', fontsize=12)

plt.ylabel('缺失值占比(%)', fontsize=12)

plt.xticks(rotation=45)

plt.grid(axis='y', alpha=0.3)

plt.tight_layout()

plt.savefig('缺失值占比图.png', dpi=300)

plt.show()

else:

print("\n=== 缺失值探查结果 ===")

print("无缺失值!")

# 执行缺失值探查

if df is not None:

missing_value_analysis(df)

2. 维度 2:分类变量探查(占比分析)

针对地区、产品类型、客户类型等分类字段,分析分布占比:


def categorical_analysis(df, cat_cols):

"""分类变量占比探查与可视化"""

print("\n=== 分类变量占比分析 ===")

for col in cat_cols:

if col in df.columns:

# 计算占比

cat_count = df[col].value_counts()

cat_ratio = (cat_count / len(df) * 100).round(2)

print(f"\n{col} 占比:")

print(pd.DataFrame({

'数量': cat_count,

'占比(%)': cat_ratio

}))

# 可视化(饼图)

plt.figure(figsize=(8, 8))

plt.pie(cat_count, labels=cat_count.index, autopct='%1.1f%%',

startangle=90, colors=sns.color_palette('viridis'), explode=[0.05]*len(cat_count))

plt.title(f'{col} 分布占比', fontsize=14, fontweight='bold')

plt.axis('equal')

plt.tight_layout()

plt.savefig(f'{col}_占比图.png', dpi=300)

plt.show()

# 定义分类字段列表(按需修改)

categorical_cols = ['REGION', 'PRODUCT_TYPE', 'CUSTOMER_TYPE']

if df is not None:

categorical_analysis(df, categorical_cols)

3. 维度 3:数值变量探查(分布与异常值)

针对销售金额、销量、单价等数值字段,分析分布特征与异常值:


def numerical_analysis(df, num_cols):

"""数值变量分布与异常值探查"""

print("\n=== 数值变量统计特征 ===")

# 统计描述(均值、标准差、中位数、四分位数等)

numerical_desc = df[num_cols].describe().round(2)

print(numerical_desc)

# 可视化:直方图(分布)+ 箱线图(异常值)

fig, axes = plt.subplots(2, len(num_cols), figsize=(15, 10))

fig.suptitle('数值变量分布与异常值探查', fontsize=16, fontweight='bold')

for i, col in enumerate(num_cols):

# 直方图(分布)

sns.histplot(df[col], ax=axes[0, i], bins=20, color='#2E86AB', alpha=0.7, kde=True)

axes[0, i].set_title(f'{col} 分布', fontsize=12)

axes[0, i].set_xlabel('')

axes[0, i].grid(alpha=0.3)

# 箱线图(异常值)

sns.boxplot(y=df[col], ax=axes[1,i], color='#F39C12', alpha=0.7)

axes[1, i].set_title(f'{col} 异常值', fontsize=12)

axes[1, i].set_xlabel('')

axes[1, i].grid(axis='y', alpha=0.3)

plt.tight_layout()

plt.savefig('数值变量探查图.png', dpi=300)

plt.show()

# 定义数值字段列表(按需修改)

numerical_cols = ['SALE_AMOUNT', 'QUANTITY', 'UNIT_PRICE']

if df is not None:

numerical_analysis(df, numerical_cols)

4. 维度 4:变量相关性探查(数值字段)

分析数值变量间的线性相关性,识别关键关联特征:


def correlation_analysis(df, num_cols):

"""数值变量相关性探查"""

# 计算相关系数(Pearson相关系数)

corr_matrix = df[num_cols].corr().round(3)

print("\n=== 数值变量相关性矩阵 ===")

print(corr_matrix)

# 可视化(热力图)

plt.figure(figsize=(8, 6))

sns.heatmap(corr_matrix, annot=True, cmap='RdYlBu_r', vmin=-1, vmax=1,

square=True, linewidths=0.5, cbar_kws={'shrink': 0.8})

plt.title('数值变量相关性热力图', fontsize=14, fontweight='bold')

plt.tight_layout()

plt.savefig('相关性热力图.png', dpi=300)

plt.show()

if df is not None:

correlation_analysis(df, numerical_cols)

5. 维度 5:时间趋势探查(针对日期字段)

分析销售数据随时间的变化趋势:


def time_trend_analysis(df, date_col, value_col):

"""时间趋势探查(按日/月聚合)"""

if date_col not in df.columns or value_col not in df.columns:

print("\n时间趋势分析:缺少日期字段或数值字段,跳过!")

return

# 按月份聚合(统计每月销售金额)

df['YEAR_MONTH'] = df[date_col].dt.to_period('M') # 新增年月字段

time_trend = df.groupby('YEAR_MONTH')[value_col].sum().reset_index()

time_trend['YEAR_MONTH'] = time_trend['YEAR_MONTH'].astype(str) # 转换为字符串便于显示

print("\n=== 时间趋势分析(按月聚合) ===")

print(time_trend)

# 可视化(折线图)

plt.figure(figsize=(14, 6))

sns.lineplot(x='YEAR_MONTH', y=value_col, data=time_trend, marker='o',

linewidth=2, markersize=6, color='#8E44AD')

plt.title(f'每月{value_col}趋势', fontsize=14, fontweight='bold')

plt.xlabel('年月', fontsize=12)

plt.ylabel(value_col, fontsize=12)

plt.xticks(rotation=45)

plt.grid(alpha=0.3)

plt.tight_layout()

plt.savefig('时间趋势图.png', dpi=300)

plt.show()

if df is not None:

time_trend_analysis(df, date_col='SALE_DATE', value_col='SALE_AMOUNT')

四、运行与测试步骤(手把手操作)

1. 前置准备

  1. 安装 Python 依赖与 Oracle Instant Client,配置环境变量;
  1. 确认 Oracle 数据库服务正常运行,获取登录用户名、密码、主机 IP、端口号、服务名;
  1. 替换代码中的db_config(数据库配置)和query_sql(SQL 查询语句),确保目标表存在。

2. 运行代码

  1. 按顺序执行代码(分单元格执行,如 Jupyter Notebook,便于调试);
  1. 观察控制台输出:
    • 数据库连接状态(成功 / 失败);
    • 数据读取结果(记录数、字段数);
    • 各维度探查结果(缺失值、分类占比、统计特征、相关性等);
  1. 查看项目目录:生成缺失值占比图、分类变量饼图、数值变量探查图、相关性热力图、时间趋势图等可视化文件。

3. 结果解读示例

  • 缺失值:若 “PRODUCT_TYPE” 字段缺失率 10%,需评估是否影响分析(可删除或填充);
  • 分类占比:华东地区销售占比 40%,为主要市场;电子产品占比 60%,是核心产品;
  • 数值分布:销售金额集中在 1000-5000 元,无明显异常值;
  • 相关性:销量与销售金额相关系数 0.95,呈强正相关(符合业务逻辑);
  • 时间趋势:6-8 月销售金额峰值,可能为旺季。

五、避坑指南(新手必看)

1. Oracle 数据库连接失败

  • 错误现象:cx_Oracle.Error: ORA-12170: TNS:连接超时或ORA-12514: TNS:监听程序当前无法识别连接描述符中请求的服务;
  • 解决方法
    1. 检查主机 IP、端口号、服务名是否正确(可通过tnsping 服务名测试网络连通性);
    1. 确认 Oracle 数据库服务已启动(Windows:服务中启动 OracleServiceORCL;Linux:systemctl start oracle);
    1. 关闭防火墙(或开放 1521 端口),避免端口被拦截;
    1. 客户端版本与数据库版本兼容(如 Oracle 19c 数据库搭配 19c 客户端)。

2. 中文乱码问题

  • 错误现象:查询结果中中文字段显示为问号(?);
  • 解决方法
    1. 连接数据库时指定编码:conn = cx_Oracle.connect(user, password, dsn, encoding='utf8', nencoding='utf8');
    1. 确保 Oracle 数据库字符集为 UTF-8(可执行select userenv('language') from dual;查询,需包含UTF8)。

3. 数据量过大导致内存溢出

  • 错误现象:读取大量数据(百万级)时,Python 报错 “MemoryError”;
  • 解决方法
    1. 用 SQLWHERE条件筛选目标数据(如按日期范围),减少读取量;
    1. 分块读取数据:pd.read_sql(query_sql, conn, chunksize=10000),逐块处理;
    1. 聚合查询:用GROUP BY在 Oracle 端完成聚合,减少返回数据量。

4. 日期字段处理错误

  • 错误现象:日期字段读取后为字符串,无法进行时间趋势分析;
  • 解决方法:用pd.to_datetime(df['SALE_DATE'])转换为 datetime 类型,或在 SQL 中指定日期格式:TO_CHAR(SALE_DATE, 'YYYY-MM-DD') AS SALE_DATE。

六、进阶扩展(按需优化)

1. 批量执行多 SQL 查询


def batch_query(db_config, sql_list):

"""批量执行多个SQL查询,返回结果字典"""

results = {}

conn = cx_Oracle.connect(**db_config)

for sql_name, sql in sql_list.items():

try:

df = pd.read_sql(sql, conn)

results[sql_name] = df

print(f"{sql_name}:读取 {len(df)} 条记录")

except Exception as e:

print(f"{sql_name} 执行失败:{e}")

results[sql_name] = None

conn.close()

return results

# 定义多SQL查询

sql_dict = {

'销售明细': "SELECT * FROM SALES_DATA WHERE SALE_DATE >= TO_DATE('2024-01-01', 'YYYY-MM-DD')",

'地区销售汇总': "SELECT REGION, SUM(SALE_AMOUNT) AS TOTAL_AMOUNT FROM SALES_DATA GROUP BY REGION"

}

# 批量执行

# batch_results = batch_query(db_config, sql_dict)

2. 分析结果导出为 Excel 报告


def export_to_excel(results, output_path):

"""将多维度探查结果导出为Excel(多sheet)"""

with pd.ExcelWriter(output_path, engine='openpyxl') as writer:

# 原始数据

df.to_excel(writer, sheet_name='原始数据', index=False)

# 分类变量占比

for col in categorical_cols:

if col in df.columns:

cat_ratio = (df[col].value_counts() / len(df) * 100).round(2)

pd.DataFrame({

'类别': cat_ratio.index,

'占比(%)': cat_ratio.values

}).to_excel(writer, sheet_name=f'{col}占比', index=False)

# 数值变量统计

df[numerical_cols].describe().round(2).to_excel(writer, sheet_name='数值统计')

# 相关性矩阵

df[numerical_cols].corr().round(3).to_excel(writer, sheet_name='相关性矩阵')

print(f"分析结果已导出至:{output_path}")

# 导出Excel(替换为实际路径)

# if df is not None:

# export_to_excel(df, 'Oracle数据分析报告.xlsx')

3. 结合 SQL 聚合与 Python 分析


# 示例:用SQL完成复杂聚合,Python仅负责可视化

sql_agg = """

SELECT

REGION,

PRODUCT_TYPE,

TO_CHAR(SALE_DATE, 'YYYY-MM') AS YEAR_MONTH,

SUM(SALE_AMOUNT) AS TOTAL_AMOUNT,

AVG(QUANTITY) AS AVG_QUANTITY

FROM SALES_DATA

GROUP BY REGION, PRODUCT_TYPE, TO_CHAR(SALE_DATE, 'YYYY-MM')

ORDER BY YEAR_MONTH, REGION

"""

df_agg = oracle_connect(sql_agg, db_config)

if df_agg is not None:

# 可视化:各地区各产品类型月度销售金额

plt.figure(figsize=(14, 8))

sns.barplot(x='YEAR_MONTH', y='TOTAL_AMOUNT', hue='REGION', data=df_agg, palette='Set2')

plt.title('各地区各产品类型月度销售金额', fontsize=14, fontweight='bold')

plt.xlabel('年月', fontsize=12)

plt.ylabel('销售金额(元)', fontsize=12)

plt.xticks(rotation=45)

plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

plt.grid(axis='y', alpha=0.3)

plt.tight_layout()

plt.savefig('地区产品月度销售图.png', dpi=300)

plt.show()

总结

本文通过 “数据库连接 - 数据读取 - 多维度探查 - 可视化分析” 的完整流程,手把手教你用 Python 实现 Oracle 数据库数据分析,核心亮点如下:

  1. 连接简单:仅需配置数据库信息,10 行代码即可读取 Oracle 数据,无需导出中间文件;
  1. 探查全面:覆盖缺失值、分类变量、数值变量、相关性、时间趋势 5 大核心维度;
  1. 代码精简:核心分析逻辑仅 300 余行,支持灵活修改(如替换表名、字段、SQL 查询);
  1. 可视化直观:生成多类图表,快速呈现数据特征,助力业务决策;
  1. 实战性强:提供避坑指南与进阶扩展(批量查询、Excel 导出、SQL 聚合联动),直接复用。

该方案适用于企业级数据分析、业务报表生成、数据质量监控等场景,无论你是数据分析新手还是有经验的开发者,都能通过本文快速掌握 Python 操作 Oracle 数据库的核心技巧,高效挖掘数据价值。来源地址:||@FiRe.BaNjInJgPt.cOm@||@FiRe.JuJiAJiU.cOm@|

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐