Как узнать, сработало ли удаление в PDO

  • Автор темы livrka1337
  • 18
  • Обновлено
  • 13, May 2024
  • #1
Я просто наткнулся на интересную вещь, когда работал с вызовами PDO в своей текущей программе.

Соответствующая часть моей программы выполняет задачу удаления одной строки таблицы, зная два значения, составляющие первичный ключ таблицы.

(В этой конкретной таблице первичный ключ представляет собой комбинацию clientCode и orderNumber.

Как вы знаете, многостолбцовый первичный ключ означает, что комбинация столбцов в первичном ключе должна быть уникальной.



Поэтому я мог бы много заказов с одинаковым номером заказа или одним и тем же кодом клиента, но у меня может быть только ОДНА строка с заданной комбинацией clientCode и orderNumber.) Это означает, что мое удаление может удалить не более одной строки из таблицы, когда я удаляю через первичный ключ.



(Он также может не удалить какие-либо строки, если не существует строки, содержащей определенный clientCode и orderNumber.)

Я был очень удивлен, обнаружив, что следующий код позволит мне удалить данную строку НЕСКОЛЬКО раз! Правильно: вы можете удалить строку (и она исчезнет, как я убедился, напрямую запросив базу данных), а затем вы можете удалить ее снова, даже если она уже исчезла! Я просмотрел определение оператора выполнения PDO в руководстве по PHP, и там сказано, что он возвращает true, если он был успешным, и false, если он был неудачным.

В этом случае не должна ли неспособность удалить строку (поскольку ее там нет) считаться НЕУспешной? Я здесь, чтобы сообщить вам, что PHP считает мои повторные удаления одной и той же строки УСПЕШНЫМИ.

На мой взгляд, это противоречит всякой логике.

Кажется очень маловероятным, что PDO действительно может работать таким образом, поэтому я предполагаю, что каким-то образом сделал что-то, чтобы непреднамеренно заставить неудачи рассматриваться как успехи, но я действительно не знаю, что это будет.

Я надеюсь, что кто-то здесь может просветить меня. Я привожу полный пример кода, демонстрирующий проблему.

Все, что вам понадобится, это копия MySQL (или, возможно, подойдет другая база данных, если SQL совместим), а затем запустить эту программу. Если я не могу найти способ заставить PDO сказать мне правду о том, сработало ли удаление или нет, я полагаю, мне придется выполнить второй запрос, чтобы увидеть, действительно ли строка исчезла после удаления - и тогда надеюсь, что второй вопрос и мне не врет!

Вот два файла, которые вам понадобятся, чтобы попробовать это самостоятельно.

 <?php

$debug = 0;

if ($debug) echo "Entering ".__FILE__."\n";

require_once dirname(__FILE__) . '/getPdoConnection.php';

//Get a database connection.

$pdo = getPDOConnection();

//Create the Heroes table.

if (createHeroesTable($pdo)) {

echo "Heroes table was successfully created.\n";

}

//Get contents of Heroes table to verify that it is empty.

$heroes = getHeroes($pdo);

echo "Heroes array:\n";

print_r($heroes);

//Create some heroes.

if (createHero($pdo, "Superman", "Kal-el", "5", "Justice League")) {

echo "Hero Superman was successfully inserted.\n";

}

if (createHero($pdo, "Robin", "Dick Grayson", "4", "Justice League")) {

echo "Hero Robin was successfully inserted.\n";

}

//Get contents of Heroes table to verify that the heroes were inserted.

$heroes = getHeroes($pdo);

echo "Heroes array:\n";

print_r($heroes);

//Determine the ID of a hero who needs to be updated.

$heroID = getHeroID($pdo, "Superman");

echo "The ID for Superman is: $heroID \n";

//Update the hero's information.

if (updateHero($pdo, $heroID, "Superman", "Clark Kent", "5", "Justice League")) {

echo "Superman's info was updated.\n";

}

//Get contents of Heroes table to verify that the update took place.

$heroes = getHeroes($pdo);

echo "Heroes array:\n";

print_r($heroes);

//Delete the hero which was just updated (Superman).

if (deleteHero($pdo, $heroID)) {

echo "Superman was deleted.\n";

}

//Delete the hero (Superman) *again*.

if (deleteHero($pdo, $heroID)) {

echo "Superman was deleted *again*.\n";

}

//Get contents of Heroes table to verify that the delete took place.

$heroes = getHeroes($pdo); //display the heroes table

echo "Heroes array:\n";

print_r($heroes);

//Delete all of the heroes.

if (deleteAllHeroes($pdo)) {

echo "All rows of the Heroes table were successfully deleted.\n";

}

//Drop the Heroes table.

if (dropHeroesTable($pdo)) {

echo "Heroes table was successfully dropped.\n";

}

exit;

function getHeroes($pdo) {

global $debug;

if ($debug) echo "Entering getHeroes()...\n";

//Fetch the heroes from the table. There is going to be at least one, otherwise we would have exited.

$sql = "select id, name, realname, rating, teamaffiliation from heroes";

$stmt = $pdo->query($sql);

$heroes = array(); //initialize heroes array which will hold the result set

while ($row = $stmt->fetch()) { //if the query returns no rows, the while loop will never start

// echo $row['id']."; ".$row['name']."; ".$row['realname']."; ".$row['rating']."; ".$row['teamaffiliation']."\n";

array_push($heroes, $row);

}

if ($debug) {

echo "heroes array:\n";

print_r($heroes);

}

return $heroes;

}

function getHeroID($pdo, $name) {

global $debug;

if ($debug) echo "Entering getHeroID($name)...\n";

$sql = "select id from heroes where name = ?";

$stmt = $pdo->prepare($sql);

$stmt->execute(array($name));

//Find the id for the hero and return it. The user selected the row from a GUI

//and can only select a single existing hero at a time.

while ($row = $stmt->fetch()) {

$heroID = $row['id'];

}

return $heroID;

}

function createHero($pdo, $name, $realname, $rating, $teamaffiliation) {

global $debug;

if ($debug) echo "Entering createHeroes($name, $realname, $rating, $teamaffiliation)...\n";

$sql = "INSERT INTO heroes (name, realname, rating, teamaffiliation) values (?,?,?,?)";

$stmt = $pdo->prepare($sql);

if($stmt->execute(array($name, $realname, $rating, $teamaffiliation))) return true;

return false;

}

function updateHero($pdo, $id, $name, $realname, $rating, $teamaffiliation) {

global $debug;

if ($debug) echo "Entering updateHero($id)...\n";

$sql = "UPDATE heroes SET name=?, realname=?, rating=?, teamaffiliation=? WHERE id=?";

$stmt = $pdo->prepare($sql);

if($stmt->execute(array($name, $realname, $rating, $teamaffiliation, $id))) return true;

return false;

}

function deleteHero($pdo, $id) {

global $debug;

if ($debug) echo "Entering deleteHero($id)...\n";

$sql = "delete from heroes where id=?";

$stmt = $pdo->prepare($sql);

if($stmt->execute(array($id))) return true;

return false;

}

function deleteAllHeroes($pdo) {

global $debug;

if ($debug) echo "Entering deleteAllHeroes()...\n";

$sql = "delete from heroes";

$stmt = $pdo->prepare($sql);

if($stmt->execute()) return true;

return false;

}

function createHeroesTable($pdo) {

global $debug;

if ($debug) echo "Entering createHeroesTable()...\n";

$sql = "create table heroes (

id int(11) not null auto_increment,

name varchar(30) collate utf8_unicode_ci not null,

realname varchar(30) collate utf8_unicode_ci not null,

rating int(11) not null,

teamaffiliation varchar(30) collate utf8_unicode_ci not null,

primary key(id))";

$stmt = $pdo->prepare($sql);

if ($stmt->execute()) return true;

return false;

}

function dropHeroesTable($pdo) {

global $debug;

if ($debug) echo "Entering dropHeroesTable()...\n";

$sql = "drop table heroes";

$stmt = $pdo->prepare($sql);

if ($stmt->execute()) return true;

return false;

}

?>
PHP:
 <?php function getPdoConnection() { $debug = 0; /* The values used to connect to the database are stored in an external ini file.


Read that * file and find the various values.



*/ $file = "TW.ini"; if (!$settings = parse_ini_file($file, TRUE)) throw new exception('Unable to open ' . $file . '.'); $driver = $settings['database']['driver']; $host = $settings['database']['host']; $port = $settings['database']['port']; $username = $settings['database']['username']; $password = $settings['database']['password']; $dbname = $settings['database']['dbname']; $charset = $settings['database']['charset']; if ($debug) { echo "driver: $driver\n"; echo "host: $host\n"; echo "port: $port\n"; echo "username: $username\n"; echo "password: $password\n"; echo "dbname: $dbname\n"; echo "charset: $charset\n"; } //Construct the DNS and options that are needed to connect to the database.





$dns = "$driver:host=$host;port=$port;dbname=$dbname;charset=$charset"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; if ($debug) { echo "dns: $dns\n"; echo "options:\n"; print_r($options); } //Get a database connection.



$pdo = new PDO($dns, $username, $password, $options); return $pdo; } ?>
PHP:

livrka1337


Рег
23 Dec, 2015

Тем
1

Постов
2

Баллов
12
  • 10, Jun 2024
  • #2
На самом деле это ПРОЩЕ, так что вы можете определить разницу между тем, когда движок или запрос идут битами вверх лицом вниз, или произошло ли какое-либо действие. Помните, что PDOStatement->execute используется НЕЗАВИСИМО от того, что вы выполняете для запроса, поэтому попытка разместить там результат запроса любого типа не имеет смысла. Следовательно, почему, если есть набор результатов, вы -> извлекаете, а если это вставка/удаление/обновление, вы используете ->rowcount. Это сложнее понять, когда вы только начинаете. вы начинаете вникать в сложные запросы, и это разделение становится ОЧЕНЬ желанной и даже необходимой функцией.
 

jetvpn


Рег
07 Aug, 2011

Тем
2

Постов
3

Баллов
23
  • 11, Jun 2024
  • #3
Спасибо, это ОЧЕНЬ полезно и избавляет меня от всякого горя! Я все еще удивлен, что все работает таким образом, но, по крайней мере, есть простой способ определить влияние удаления (или обновления или вставки, над которым я работаю дальше).
 

Баир1


Рег
03 Feb, 2014

Тем
1

Постов
3

Баллов
13
Тем
49554
Комментарии
57426
Опыт
552966

Интересно