PHP - 错误时不抛出PDOException,返回一个空数组(SQL Server)

时间:2016-09-13 09:59:54

标签: php sql-server pdo

如果我理解正确,我正在使用以下堆栈:PHP< - > PDO< - > MS SQL DBLIB< - > freetds< - > MS SQL Server。

$pdo = new \PDO('dblib:host=192.168.0.10:1433;dbname=MyDb;charset=UTF-8', 'mydb', 'secret', [
    \PDO::ATTR_CASE => \PDO::CASE_NATURAL,
    \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
    \PDO::ATTR_STRINGIFY_FETCHES => false,
]);
$statement = $pdo->prepare("EXEC [dbo].[sp_MyStoredProcedure] 1, 2, 3");
if ( ! $statement->execute()) {
    throw new \ErrorException('Error executing sp_MyStoredProcedure');
}
$data = $statement->fetchAll(\PDO::FETCH_ASSOC);

我将ERRMODE设置为ERRMODE_EXCEPTION,并且存储过程中发生 515 错误,但没有抛出异常,为什么? $data正在存储空数组,我认为这是执行存储过程的正确结果。为了解决这个问题,我添加了检查$statement->errorInfo()[1],因为我不确定以这种方式检查错误是否合适:

if ( ! $statement->execute() || $statement->errorInfo()[1]) {
    throw new \ErrorException('Error executing sp_MyStoredProcedure');
}

我是否正确地进行了这项检查?

详细的$ statement-> errorInfo():

array (
  0 => '00000',
  1 => 515,
  2 => 'General SQL Server error: Check messages from the SQL Server [515]  (severity 16) [(null)]',
  3 => -1,
  4 => 16,
)

另外根据article错误 515 是将NULL插入到非NULL的列中的错误。但是为什么我在Microsoft SQL Server Management Studio或tsql(freetds-bin)中执行EXEC [dbo].[sp_MyStoredProcedure] 1, 2, 3时没有看到此错误?

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。

解决方案 - 为存储过程中的临时表列显式指定null-ability。

在:

create table #resultsTable(
    paging_id int,
    pt_key bigint,
    pt_ctkeyfrom int
)

后:

create table #resultsTable(
    paging_id int NULL,
    pt_key bigint NULL,
    pt_ctkeyfrom int NULL
)

对我来说问题已经解决了。

不幸的是,我不知道如何在不改变程序代码的情况下解决。

答案 1 :(得分:-1)

要查看您的异常,您需要在抛出它们时捕获它们。您的代码不会监听PDOException,因为您错过了try-catch语句。

以下是处理抛出异常的方法时的错误检查示例:

$pdo = null;

try {
    $pdo = new \PDO('dblib:host=192.168.0.10:1433;dbname=MyDb;charset=UTF-8', 'mydb', 'secret', [
        \PDO::ATTR_CASE => \PDO::CASE_NATURAL,
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
        \PDO::ATTR_STRINGIFY_FETCHES => false,
    ]);

    $statement = $pdo->prepare("EXEC [dbo].[sp_MyStoredProcedure] 1, 2, 3");

    $data = $statement->fetchAll(\PDO::FETCH_ASSOC);
}
catch( PDOException $e ) {
    print_r( $pdo->errorInfo() );   //  PDO::errorInfo() returns an array
                                    //  [0] : sql error code
                                    //  [1] : driver error code
                                    //  [2] : error message
}

您看到您不必抛出任何自定义异常,您必须相对于其性质捕获它们(PDO抛出PDOException)。

您最终可能会抛出自己的异常,但是您需要在另一段代码中捕获它们。这是一个适合您原始代码的示例:

$pdo = null;

try {
    $pdo = new \PDO('dblib:host=192.168.0.10:1433;dbname=MyDb;charset=UTF-8', 'mydb', 'secret', [
        \PDO::ATTR_CASE => \PDO::CASE_NATURAL,
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
        \PDO::ATTR_STRINGIFY_FETCHES => false,
    ]);

    $statement = $pdo->prepare("EXEC [dbo].[sp_MyStoredProcedure] 1, 2, 3");

    if ( ! $statement->execute()) {
        throw new \ErrorException('Error executing sp_MyStoredProcedure');
    }

    $data = $statement->fetchAll(\PDO::FETCH_ASSOC);
}
catch( PDOException $e ) {
    print_r( $pdo->errorInfo() );   //  PDO::errorInfo() returns an array
                                    //  [0] : sql error code
                                    //  [1] : driver error code
                                    //  [2] : error message
}
catch( ErrorException $e ) {
    print_r( $e );
}