CodeIgniter 3 连 Oracle 必须启用 oci8 扩展(非 pdo_oci),正确配置 hostname(如 //host:port/service)、char_set=AL32UTF8、dbcollat='',并调用 initialize() 验证连接。

OCI8 驱动必须启用且版本匹配
CodeIgniter 3 连 Oracle 不是开箱即用的,核心前提是 PHP 已编译或启用了 oci8 扩展(不是 pdo_oci),且 Oracle 客户端库(如 Oracle Instant Client)已正确安装并被 PHP 加载。运行 php -m | grep oci 或查看 phpinfo() 中的 OCI8 模块状态,确认版本与 Oracle 服务端兼容(例如 Oracle 12c/19c 推荐 oci8 2.2.0+)。若扩展未启用,$db['default']['dbdriver'] = 'oci8' 会静默失败,后续所有数据库操作都会报 Fatal error: Call to a member function xxx() on null。
hostname 格式必须是完整 TNS 描述符或 SID/Service Name 形式
Oracle 的 hostname 不是简单的 localhost,它实际承载的是连接标识。常见合法写法有两类:
-
localhost/XE:适用于本地 XE 实例,其中XE是服务名(非 SID) -
//192.168.1.100:1521/orclpdb:使用 Easy Connect 格式,orclpdb是可插拔数据库的服务名 -
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.100)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orclpdb))):完整 TNS 描述符,需注意括号和等号间不能有空格
错误示例:localhost:1521:orcl(冒号分隔不被 oci8 支持)、localhost/orcl(缺少端口或协议信息)——这些会导致 ORA-12154: TNS:could not resolve the connect identifier。
字符集与数据库校对必须显式指定
Oracle 对字符集敏感,CI 默认的 utf8 会失效。必须将 char_set 设为 Oracle 实际使用的字符集(通常是 AL32UTF8),且 dbcollat 留空(Oracle 不使用 MySQL 风格的 collation):
$db['default']['char_set'] = 'AL32UTF8'; $db['default']['dbcollat'] = '';
若设错(比如填成 utf8mb4),连接虽可能成功,但中文插入/查询会乱码或报 ORA-12705: Cannot access NLS data files or invalid environment specified。另外,database 字段在 oci8 下通常为空字符串(''),因为服务名已在 hostname 中体现;填了反而可能触发 ORA-12505 错误。
初始化后必须调用 initialize() 才能验证连接有效性
$this->load->database() 即使凭据错误也返回对象,不能靠返回值判断成败。真正检测连接是否就绪,得在加载后主动调用 $this->db->initialize():
$this->load->database($config, TRUE);
if ( ! $this->db->initialize()) {
// 连接失败:可能是用户名密码错、TNS 解析失败、监听未启动等
log_message('error', 'Oracle connection failed: ' . $this->db->error()['message']);
return FALSE;
}
注意:不要用 @$this->db->initialize() 抑制错误——它会掩盖真实原因(如权限不足时抛出的 ORA-01017),应结合 $this->db->error() 查具体 Oracle 错误码。OCI8 连接池行为也不同于 MySQL,pconnect 在多数部署中建议设为 FALSE,避免长连接泄漏。
Oracle 连接最易卡在 TNS 解析和字符集上,调试时优先检查 tnsping 能否通、sqlplus user/pass@tns_alias 是否能登录,再比对 CI 配置里的 hostname 和 char_set —— 这两处错一个,后面全白忙。


















