Хорошо, я в тупике с этим. У меня есть таблица в моей базе данных, где я не могу удалить строки через PDO (я заметил это поведение в течение нескольких недель, он работал отлично до этого).
Мой PHP-код:
// Echo's have been added for testing. try{ $dbh = new PDO($hostname, $username, $password); $sql="delete from sources where workFlowID=".$ID.";"; $numRows=$dbh->exec($sql); echo "There were $numRows deleted with: $sql <br><br>"; $sql="delete from workflow where id=".$ID." limit 1;"; // I have only put the 'or die' section in this today to try to see where // it was having problems. It carries through happily as the output // below shows. $numRows=$dbh->exec($sql) or die(print_r($dbh->errorInfo(), true)); // This is the problem delete... echo "There were $numRows deleted with: $sql <br><br>"; $dbh=null; } catch(PDOException $e){ echo 'Error : '.$e->getMessage(); exit(); }
С выходом:
There were 1 deleted with: delete from sources where workflowid=1; There were 1 deleted with: delete from workflow where id=1 limit 1;
Однако, когда я смотрю в базе данных, я все еще вижу свою запись, сидящую в моей workflow
таблице.
Я проверил и дважды проверил типы данных. ID и workflowID – оба типа. Они снабжаются одной и той же переменной на несколько строк друг от друга.
Я думал, что это может быть проблема с разрешениями, поэтому у меня есть покрытое покрытие, которое выглядит следующим образом:
mysql> grant all privileges on storeProcess.* to 'myusername'@'localhost' with grant option; Query OK, 0 rows affected (0.19 sec)
Затем я подумал, что это может быть какая-то фанковая синхронизация / перегрузка / whothehellknowswhat проблема, поэтому я создал триггер в таблице рабочих процессов, чтобы выполнить работу приложения и очистить другие таблицы. Затем я изменил свой код PHP на это:
// Echo's have been added for testing. try{ $dbh = new PDO($hostname, $username, $password); $sql="delete from workflow where id=".$ID." limit 1;"; $numRows=$dbh->exec($sql) or die(print_r($dbh->errorInfo(), true)); echo "There were $numRows deleted with: $sql <br><br>"; $dbh=null; } catch(PDOException $e){ echo 'Error : '.$e->getMessage(); exit(); }
Теперь выход:
There were 1 deleted with: delete from workflow where id=1 limit 1;
Но опять же запись все еще есть.
mysql> select count(*) from workflow where id=1; +----------+ | count(*) | +----------+ | 1 | +----------+ 1 row in set (0.00 sec)
У меня, конечно, нет проблем с удалением записи с консоли с помощью той же самой команды, когда я вошел в систему, используя имя пользователя / пароль учетной записи, используемой PDO (триггер работает отлично и удаляет данные из остальных таблиц):
mysql> delete from workflow where ID=1; Query OK, 1 row affected (0.00 sec) mysql> select count(*) from workflow where id=1; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)
Так что происходит не так?
Это работает на рабочем столе (Win XP, ничего необычного, стандартного типа SOE от крупной корпорации).
Я не использую транзакции во время этих запросов. Кроме того, есть только несколько пользователей, использующих приложение, и во время чего он не попадает в высокий процессор.
Я возьму код и схему домой, чтобы протестировать его под Linux и опубликую результаты, когда вернусь.
Обновление: я только что переместил его в свою Linux-систему дома. Никаких изменений вообще.
Редактировать:
Я изменил свой код, как это было предложено:
try{ $dbh = new PDO($hostname, $username, $password); $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, true); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql="delete from sources where workflowid=".$ID.";"; //echo $sql."<br><br>"; $numRows=$dbh->exec($sql); echo "There were $numRows deleted with:<b> $sql </b><br><br>"; $sql="delete from workflow where id=".$ID." limit 1;"; $numRows=$dbh->exec($sql); echo "There were $numRows deleted with:<b> $sql </b><br><br>"; $sql="delete from workflow where id=".$ID." limit 1;"; $numRows=$dbh->exec($sql); echo "There were $numRows deleted with:<b> $sql </b><br><br>"; $dbh=null; } catch(PDOException $e){ echo 'Error : '.$e->getMessage(); //exit(); }
Я запустил его со следующим выходом:
There were 601 deleted with: delete from sources where workflowid=77; There were 1 deleted with: delete from workflow where id=77 limit 1; There were 0 deleted with: delete from workflow where id=77 limit 1;
Строка все еще не удалялась:
mysql> select count(*) from workflow where id=77; +----------+ | count(*) | +----------+ | 1 | +----------+ 1 row in set (0.00 sec)
Функция PDO::exec()
возвращает количество затронутых строк, включая 0, если ни одна строка не затронута.
Строка вроде этого будет die()
потому что exec
вернет 0
который интерпретируется как логическое false.
$dblink->exec("UPDATE `sometable` SET `somecolumn`=0 WHERE `somecolumn`=0") or die("Never use die for error handling.");
Лучшей практикой обработки ошибок для PDO является использование исключений PDO. Включить исключения PDO (класса PDOException, см. Docs) следующим образом:
//enable Exception mode (uncaught exceptions work just like die() with the benefit of giving you details in logs of where execution was stopped and for what reason) $pdoDBHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Удалить or die()
и exit();
и включить режим исключения. Держу пари, это устранит вашу «странную» проблему. Также взгляните на бросание Исключений в PHP, даже с процедурным кодом (для замены die()
и exit()
.
exit
BTW останавливает выполнение так же, как и die
, за исключением того, что он полезен в режиме CLI, потому что он возвращает код успеха / ошибки в операционную систему. Это действительно не предназначено для обработки ошибок.