教材讲了三个工具:SQL*Plus(敲命令)、EM(点界面)、DBCA(建库向导)。 它们不是三套数据库,是三个入口,管的是同一个实例。本篇把它们的关系讲清, 再在沙箱里把三条路挨个试一遍。
上一篇讲「怎么把库装出来」,这一篇讲「装好之后从哪儿进去」。 这三个工具会在后面每一章反复出现:7、8 章的表空间用 SQLPlus 建, 16 章的备份用 RMAN 命令行,19 章的项目用 Java 客户端连。 先记住一件事:界面会换,SQL 不会。 EM 上点的每一个按钮,背后都是一条 SQL*——所以先学 SQL,界面随时换。
一、SQL*Plus:最老,也最不会消失
SQLPlus 是 Oracle 从第一天就带着的命令行工具。它的地位一直没被取代,原因很实在: 它是唯一一个「任何环境都一定有」的工具——服务器上不一定有图形界面,但一定有它。 它有两种命令,规矩不一样:*
| 类型 | 例子 | 要不要分号 |
|---|---|---|
| SQL 命令 | select * from emp; |
要,分号是「执行」的意思 |
| SQL*Plus 命令 | desc emp、set linesize 200 |
不要,回车就执行 |
这条差别新手最容易卡:敲了 select * from emp 不加分号,
它会显示 2 然后干等——那个 2 是「缓冲区第 2 行」,不是错误。
它在等你把语句写完。
日常用的几条: desc 看表结构、set linesize/pagesize 调显示、spool 把输出存成文件、
@脚本.sql 执行脚本、/ 重跑上一条、! 切到系统命令行。
二、EM 与 DBCA:把命令包成界面
EM(Enterprise Manager) 是浏览器里的管理台。注意它分两种,别搞混: EM Express 是数据库自带的(配一下就能用,功能少); EM Cloud Control 是单独的产品(要另装、另买,能管几百个库)。教材里演示的是前者。 DBCA(Database Configuration Assistant) 是建库向导。 它做的是第 1.3 节装完之后的那一步:装软件不等于有库,软件是程序,库是数据文件加实例。 DBCA 有个容易被忽略的用处:它能「只生成脚本,不执行」。 这个选项价值很高——生产环境建库,标准做法就是先生成脚本、审一遍、再跑, 而不是在界面上点二十下,事后谁也说不清当时选了什么。
三、三个工具,一条线
把三个工具串起来看,它们其实是一条流水线:
| 阶段 | 工具 | 干什么 |
|---|---|---|
| 装软件 | 安装程序(1.3) | 把 Oracle 的程序文件铺到盘上 |
| 建库 | DBCA | 建数据文件、控制文件、日志文件,起实例 |
| 日常操作 | SQL*Plus / SQL Developer | 敲 SQL、建表、查数据 |
| 监控与调优 | EM / AWR 报表 | 看性能、找慢 SQL、看等待事件 |
这条线说明一件事: DBCA 干的是「造库」,SQL*Plus 干的是「用库」,EM 干的是「看库」。 三者不重叠,缺一不可。 所以「学 Oracle 先学哪个」这个问题,答案很明确:SQL。 因为另外两个的产物,最终都要落到 SQL 上。
四、沙箱里的三条路
这一篇的 Demo 会把三条路挨个试一遍:客户端在不在(which sqlplus)、监听端口通不通(1521)、
Python 驱动能不能 import。
三个都失败,但失败的方式不一样,这才是要看的:which 给 None 是「本机没有这个程序」;
connect_ex 给非 0 是「端口上没人应答」;import 报 ModuleNotFoundError 是「库没装」。
三种失败对应三层缺失:客户端、服务端、驱动。
排障时先分清是哪一层,否则会一直在装驱动,而问题其实是没有服务端。
五、动手 Demo:三条路挨个测:客户端、端口、驱动
这段代码没有任何 Oracle 依赖,全是标准库——shutil.which 找程序、socket 探端口、
importlib 试导入。这三招在排查任何「连不上」的问题时都用得上。
测完的结论是:三条路一条都不通,所以本课全部改用 SQLite。
import shutil, socket, importlib
# 入口一:客户端在不在
shutil.which('sqlplus') # None 就是没有
# 入口二:监听端口有没有人应答
s = socket.socket(); s.settimeout(0.5)
s.connect_ex(('127.0.0.1', 1521)) # 0 才是连上了
# 入口三:Python 驱动
for m in ('oracledb', 'cx_Oracle'):
try:
importlib.import_module(m); print(m, 'OK')
except Exception as e:
print(m, type(e).__name__)
# 三条都不通,于是:能等价的用 SQLite 真跑
c = sqlite3.connect(':memory:'); ...
实跑输出:
--------------------------------------------------------------------
第四课:管理工具——三条路,一条都走不通
--------------------------------------------------------------------
**教材讲了三个工具:SQL*Plus(敲命令)、企业管理器 EM(点界面)、DBCA(建库向导)。**
**它们不是三套数据库,是三个入口,管的是同一个实例。**
入口一:SQL*Plus——本机有没有
--------------------------------------------------------------------
`shutil.which('sqlplus')` → **None**
**None 就是没有。** **没有客户端,连 `sqlplus / as sysdba` 都没得敲。**
[Oracle 原码 · 本沙箱不执行]
| sqlplus / as sysdba
| SQL> SELECT * FROM v$version;
入口二:监听端口 1521——有没有人在听
--------------------------------------------------------------------
`socket.connect_ex(('127.0.0.1', 1521))` → **10035**
**0 才是「连上了」。**
**这次拿到的是 10035,在 Windows 上是 `WSAEWOULDBLOCK`:**
**连接没在超时时间内完成——端口上没人应答。**
**1521 是 Oracle 监听器的默认端口**,**客户端连远程库时,先连监听、监听再把会话交给实例。**
入口三:Python 驱动——能不能 import
--------------------------------------------------------------------
`import oracledb` → **ModuleNotFoundError**
`import cx_Oracle` → **ModuleNotFoundError**
**两个驱动都没有。**
**就算有,也只是客户端,还得有个真库让它连。**
三条路都不通,所以本课这么干
--------------------------------------------------------------------
**能等价的用 SQLite 真跑;不能等价的贴 Oracle 原码。**
**判断标准很简单:**
**这句话换到 SQLite 上语义不变 → 跑;**
**语义变了或者根本没有对应物 → 只贴原码。**
SQL> select ename, job, sal from emp where deptno = 10 order by sal desc
ENAME JOB SAL
---------------------
KING PRESIDENT 5000
CLARK MANAGER 2450
MILLER CLERK 1300
已选择 3 行
**上面这条能跑,因为它是标准 SQL,两边语义一样。**
**下面这条不能跑,因为 `dba_users` 是 Oracle 的数据字典视图:**
[Oracle 原码 · 本沙箱不执行]
| SELECT username, account_status FROM dba_users;
该视图记录全库账号,只有 DBA 能查;SQLite 没有账号体系。
三个工具分别管什么
--------------------------------------------------------------------
SQL> select name, form, job from tool
NAME FORM JOB
----------------------------------------------------
SQL*Plus 命令行 敲 SQL、跑脚本、看执行计划
EM 浏览器界面 看性能图表、点着做备份、管会话
DBCA 图形向导 建库、删库、配模板、生成建库脚本
已选择 3 行
**三者最终的产物是一样的:**
**SQL*Plus 敲的 SQL,DBCA 也生成成脚本;EM 上点的按钮,背后也是 SQL。**
**所以先学 SQL,界面随时换。**
shutil.which 查的是 PATH 环境变量里的可执行文件,不是「装没装」。
装了但没加进 PATH,它照样返回 None。
所以 None 只说明「命令行里敲不出这个命令」,不能直接等同于「没装」。
connect_ex 和 connect 的区别:它不抛异常,直接返回错误码。
0 是成功;
Windows 上常见 10061(连接被拒绝,端口有人但服务没起)和 10035(超时,包被丢了或者防火墙挡了)。
这次拿到的是 10035——端口上没人应答。
ModuleNotFoundError 说明的是「Python 找不到这个模块」,和 Oracle 装没装是两件事。
这两个驱动(oracledb、cx_Oracle)都只是客户端,就算装上了,也还得有个真库让它们连。
最后那条 select ... from emp 能跑,是因为它是标准 SQL。
而 dba_users 不能跑,因为它查的是 Oracle 的账号体系——
SQLite 没有账号、没有模式、没有表空间,这一类查询永远演示不了。
30 秒实验
- 把
connect_ex的端口换成 80 和 443,看看本机有没有在跑 Web 服务。 同一段代码,换个端口号就是通用的端口扫描器。 - 用
shutil.which找python、node、mysql、psql四个命令,看看这台机器上有几个。 这就是「环境清单」的最简版。 - 把
importlib.import_module换成sqlite3,确认它一定能成功。 标准库和第三方库的区别,一行代码就能验。
常见误区
- 把
sqlplus装上了就以为有数据库了。 客户端只是「电话机」, 没装服务端就是没人接电话。 这两件事必须分开想。 - 在 SQLPlus 里给 SQLPlus 命令加分号。
desc emp;会报错(SP2-0734), 因为分号会被当成表名的一部分。分号只属于 SQL。 - 用 EM 建表,事后说不清建了什么。 界面操作的产物没有留痕, 正规做法是「界面生成脚本 → 审脚本 → 跑脚本」,DBCA 就有这个选项。
自测三问(点开对答案)
1. SQL*Plus 里敲了 `select * from emp` 没加分号,屏幕显示一个 `2`,是什么意思? —— **那个 `2` 是缓冲区行号**,表示第二行已经存进缓冲区, **它在等你继续输入或者打分号。** 不是错误,也没卡死。 2. EM Express 和 EM Cloud Control 差在哪? —— **Express 是数据库自带的**,配一下就能用,只管一个库; **Cloud Control 是单独的产品**,要另装另买,能集中管几百个库。 3. `which sqlplus` 返回 None,能断定这台机器没装 Oracle 吗? —— **不能。** 它只说明 PATH 里没有这个命令。 **可能装了但没配环境变量,也可能是只装了服务端没装客户端工具。**下一篇讲启动与关闭:startup 三步、shutdown 四档。 这是全书第一次出现「你在哪一步决定你能做什么」的概念, 后面所有运维章节都建立在这个三阶段模型上。
- ☐ (本篇完,下一篇 1.5 启动与关闭数据库实例)