不要通过 PDO 连接 oracle 数据库和 PHP

Posted

技术标签:

【中文标题】不要通过 PDO 连接 oracle 数据库和 PHP【英文标题】:Do not connect oracle database with PHP through PDO 【发布时间】:2018-05-10 02:55:21 【问题描述】:

我想默认通过 PDO 与 php 连接 oracle bd 中的 oracle Schema 数据库,但它抛出了这个错误:

致命错误:未捕获的 PDOException:SQLSTATE[42S02]: pdo_oci_handle_factory: ORA-12154: TNS: 无法解析连接 在中指定的标识符 (ext\pdo_oci\oci_driver.c:640) C:\xampp\htdocs\ORACLE\52conexion3.php:9 堆栈跟踪:#0 C:\xampp\htdocs\ORACLE\52conexion3.php(9): PDO->__construct('oci:host=localh...', 'hr', 'hr') #1 main 投入 C:\xampp\htdocs\ORACLE\52conexion3.php 第 9 行

    <!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<?php

    $base = new PDO('oci:host=localhost/XE; dbname= Schema - HR', 'hr','hr');

?>
</body>
</html>

在连接中的 sql developer 中,“shema”的 bd 在哪里,我右键单击查看属性并且我输入的数据是正确的,它显示连接名称:Schema - HR ,用户:hr,密码:hr,网络别名:XE

其他尝试但仍然无效:

$base = new PDO('oci:host=localhost;dbname=Schema - HR', 'hr','hr');

$base = new PDO("oci:host=localhost;dbname=Schema - HR", "hr","hr");

$base = new PDO("oci:host=localhost/XE;dbname=Schema - HR", "hr","hr");

$base = new PDO("oci:host=XE;dbname=Schema - HR", "hr","hr");

$base = new PDO('oci:host=localhost;dbname="Schema - HR"', 'hr','hr');

我检查了 .ini 文件,它显然是正确的“extension = php_pdo_oci.dll”。

注意:我搜索了 php 手册,当我没有与 pdo 连接但通过程序我以这种方式(使用 oci_connect)进行连接时,它可以正常工作:

$connection = oci_connect('hr', 'hr', 'localhost/XE');

// oci_connect: 资源oci_connect(string$username,string$password[,string$connection_string[,string$character_set[,int$session_mode]])

【问题讨论】:

猜测 - 它不喜欢数据库名称中的空格。 我尝试使用其他数据库(名称不带空格“prueba”但也不起作用:/ 这个“localhost/XE”语法是什么? host 应该是主机名,应该是(DNS)可解析的名称;它不应包含斜杠。 我在一个论坛上看到他们是这样说的,但我尝试了很多方法(见帖子末尾)。 不确定 PDO Oracle 驱动程序是否专门处理/拆分主机名:github.com/php/php-src/blob/master/ext/pdo_oci/… - 但手册说它属于 dbname= 参数:php.net/manual/en/ref.pdo-oci.connection.php 【参考方案1】:

如 PHP manual page 和 mentioned in a comment by mario 中所述,OCI 的 PDO DSN 在其定义中使用 dbname,而不是 schemahost

$conn = new PDO('oci:dbname=localhost/XE', $user, $pass);

您使用的localhost/XE 格式是“EZCONNECT”字符串。第一部分定义主机(localhost),第二部分定义服务(XE)。

您也可以使用“常规”连接字符串(通常在 tnsnames.ora 文件中定义):

$conn_string = '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XE)))';
$conn = new PDO('oci:dbname=' . $conn_string, $user, $pass);

【讨论】:

我以为 oracle 和 mysql 都是一样的,我在看一个 PDO 教程(但他们使用 mysql bd 和 phpmyadmin),他们放了 4 个字段(正如我在主题中写的) .显然它们是不同的,ORACLE 只需要 3 个字段:) 是否正确?现在它对我有用,但我想留下疑问。注意:我试着把 $ conn = new PDO ('oci: dbname = localhost', $ user, $ pass);没有 XE 并且它运行良好,为什么会这样?提前致谢 documentation 显示连接字符串的所有部分,host 除外,作为可选。 Quote: 如果用户指定了服务名称,那么侦听器会将用户连接到该特定数据库。否则,侦听器连接到listener.ora 文件中DEFAULT_SERVICE_listener_name 参数指定的数据库。【参考方案2】:

如果您使用 localhost 并设置 TNS,则可以只使用连接别名,在我的情况下为 orcl

$conn = new PDO('oci:dbname=orcl', $user, $pass);

在遥控器上,您可以:

$conn = new PDO('oci:dbname=hostname', $user, $pass);

【讨论】:

【参考方案3】:

在您的 php 文件夹中有 php.ini 文件,在记事本中打开它并删除前面有 oci 的语句之前的扩展名,然后再次启动服务器,然后运行您的代码。

对于您需要添加的连接性:

header("Access-Control-Allow-Origin: *");

header("Access-Control-Allow-Headers: Origin, Content-Type");

 $rest_json = file_get_contents("php://input");
 $_POST = json_decode($rest_json,true);

 $opt   = array(PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
                    PDO::ATTR_EMULATE_PREPARES   => false,
                       );
   // Create a PDO instance (connect to the database)
   $pdo     = new PDO('oci:dbname=127.0.0.1/xe;charset=CL8MSWIN1251', 'username', 'password');

【讨论】:

欢迎使用 ***:如果您发布代码、XML 或数据示例,请在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码示例”按钮 ( ) 或使用 Ctrl键盘上的 +K 可以很好地格式化和语法突出显示它!

以上是关于不要通过 PDO 连接 oracle 数据库和 PHP的主要内容,如果未能解决你的问题,请参考以下文章

PDO抽象层访问

使用 SID 和 INSTANCE_NAME 将 oracle 与 pdo 连接

是否可以将 Doctrine 与持久 PDO 连接一起使用?

如何设置数据库的连接数和连接超时时间

PHP操作PDO预处理以及事务

PHP操作PDO预处理以及事务