Mysql 无效的PDO查询不返回错误

Mysql 无效的PDO查询不返回错误,mysql,pdo,Mysql,Pdo,下面的第二条SQL语句在phpMyAdmin中返回错误: SET @num=2000040; INSERT INTO artikel( artikel_nr, lieferant_nr, bezeichnung_1, bezeichnung_1 ) SELECT @num := @num +1 AS anum, 70338, f2, f3 FROM import WHERE id >1 MySQL说: #1110 - Column 'bezeichnung_1' specified tw

下面的第二条SQL语句在phpMyAdmin中返回错误:

SET @num=2000040;
INSERT INTO artikel( artikel_nr, lieferant_nr, bezeichnung_1, bezeichnung_1 )
SELECT @num := @num +1 AS anum, 70338, f2, f3
FROM import
WHERE id >1
MySQL说:

#1110 - Column 'bezeichnung_1' specified twice
完全正确。但当我使用此函数在Symfony 1.4中运行查询时:

// run sql query
// http://erisds.co.uk/symfony/snippet-creating-debugging-complex-sql-queries-in-symfony
// http://stackoverflow.com/questions/5434702/php-quick-refactoring
// param $sql:    the query to run
// param $silent: bool if errors should be ignored
// throws:        pdo error info if statement failed and $silent=false
// returns:       pdo-statement (use for looping over result rows and error messages)
public static function runQuery($sql, $silent=false)
{
  $conn = Propel::getConnection();
  $pdo_statement = $conn->prepare($sql);

  $error = null;
  try
  {
    $pdo_statement->execute();
  }
  catch (Exception $e)
  {
    $error = $e->getMessage();
  }

  if ( !$error )
  {
    $pdo_error = $pdo_statement->errorInfo();
    $error = $pdo_error[2];
  }
  if ( !$silent && $error ) throw new Exception($error);

  return $pdo_statement;
}
/**
 * Executes multiple queries at once (separated by semicolons) and discards the results
 *
 * @param string $sql
 * @throws RuntimeException if a query failed
 */
function multi_query($sql) {
    $mysqli = new mysqli('host', 'user', 'password', 'database');


    //Execute all queries
    $index = 1;
    if ($mysqli->multi_query($sql)) {
        do {
            // next_result() fails if store_result() is not called
            if ($result = $mysqli->store_result()) {
                $result->free();
            }
            $has_next = $mysqli->more_results();
            if (!$has_next)
                return; // all queries successfully executed
            $index++;
        } while ($mysqli->next_result());
    }
    // At this point, either the multi_query() has returned false - which is
    // when the first query failed - or more_results() was true, while next_result()
    // returned false - which is when a different query failed.

    $error = $mysqli->error;
    if (!$error)
        $error = $mysqli->errno ? "errno $mysqli->errno" : '(unknown error)';
    throw new RuntimeException("mysqli query $index failed: $error");
}
不会抛出任何错误。这两条SQL语句必须同时提交,因为它们相互依赖。错误查询是根据用户输入构造的。我需要找回那个错误,否则我不能告诉数据库是否被更改,也不能告诉用户

您知道PDO为什么不抱怨无效语句吗?如果不能这样做,如何获取成功/失败信息

顺便说一句,如果没有重复的列,查询会更新数据库


这里是指向PDOStatement类的链接:

默认情况下
PDOStatement::execute()
不会引发任何异常,只会在出错时返回false。您必须通过
db->setAttribute(PDO::ATTR\u ERRMODE,PDO::ERRMODE\u EXCEPTION)
将错误处理设置为
PDO::ERRMODE\u EXCEPTION
,这是预期的行为。因为有两条语句,第一条是有效的,所以必须使用nextRowset()


来源:

如果您可以选择使用
mysqli
而不是PDO进行多重查询,那么您可以使用
mysqli\u多重查询
。由于错误处理有点复杂,下面是我的函数:

// run sql query
// http://erisds.co.uk/symfony/snippet-creating-debugging-complex-sql-queries-in-symfony
// http://stackoverflow.com/questions/5434702/php-quick-refactoring
// param $sql:    the query to run
// param $silent: bool if errors should be ignored
// throws:        pdo error info if statement failed and $silent=false
// returns:       pdo-statement (use for looping over result rows and error messages)
public static function runQuery($sql, $silent=false)
{
  $conn = Propel::getConnection();
  $pdo_statement = $conn->prepare($sql);

  $error = null;
  try
  {
    $pdo_statement->execute();
  }
  catch (Exception $e)
  {
    $error = $e->getMessage();
  }

  if ( !$error )
  {
    $pdo_error = $pdo_statement->errorInfo();
    $error = $pdo_error[2];
  }
  if ( !$silent && $error ) throw new Exception($error);

  return $pdo_statement;
}
/**
 * Executes multiple queries at once (separated by semicolons) and discards the results
 *
 * @param string $sql
 * @throws RuntimeException if a query failed
 */
function multi_query($sql) {
    $mysqli = new mysqli('host', 'user', 'password', 'database');


    //Execute all queries
    $index = 1;
    if ($mysqli->multi_query($sql)) {
        do {
            // next_result() fails if store_result() is not called
            if ($result = $mysqli->store_result()) {
                $result->free();
            }
            $has_next = $mysqli->more_results();
            if (!$has_next)
                return; // all queries successfully executed
            $index++;
        } while ($mysqli->next_result());
    }
    // At this point, either the multi_query() has returned false - which is
    // when the first query failed - or more_results() was true, while next_result()
    // returned false - which is when a different query failed.

    $error = $mysqli->error;
    if (!$error)
        $error = $mysqli->errno ? "errno $mysqli->errno" : '(unknown error)';
    throw new RuntimeException("mysqli query $index failed: $error");
}

您没有意外指定$silent=true?没有,绝对没有。我没有将$silent参数传递给函数。我尝试了您的建议;这没什么区别。问题似乎真的在于第一条语句是否有效——PDO不看第二条语句是否有错误,而是毫无怨言地愉快地执行第二条语句。当我只有一条无效语句时,无论是否设置了
PDO::ATTR_ERRMODE
,都会引发异常。我将向php.net提交一个bug报告,并在这里发布响应。bug报告的后续内容:这不是bug。因为有两条语句,第一条是有效的,所以必须使用nextRowset(),这是预期的行为。bugs.php.net上的bug状态当前已指定。人们都在积极地寻求解决方案,但还没有得到解决。这不是一个bug。您会注意到状态已更改为
而不是bug
。阅读以下内容:@Motin-我对你的编辑不太满意。你把我的全部答案换成了你的答案,取代了我的观点和接受度。你应该对我的答案发表评论,然后写下你自己的答案。看见我将签出
nextRowset
解决方案并发布结果。@Timm我重新编辑了文章以包含您的原始文章。这使得正确的答案比原始帖子不存在时更难找到(原始帖子不再正确,并且会让寻找正确答案的访问者感到困惑),但希望编辑现在符合指导原则