@VitSel

Может ли запрос SELECT приводить к удалению данных?

Я написал программу на php, которая берет из строки запроса номера строк и удаляет их из таблицы.
Вот так: mysite.com/delRows.php?q=4&row1=16&row2=11&row3=9&...
q - это количество строк для удаления, а дальше перечислены индексы строк, которые надо удалить.
В данном случае будут удалены четыре строки с индексами 16, 11, 9 и 13
Все работает прекрасно, пока я не пытаюсь удалить одну строку
Вот так: mysite.com/delRows.php?q=1&row1=6
В данном случае должна быть удалена строка 6. И это работает! Но только в первый раз.
Если я изменяю индекс и снова отправляю запрос - программа начинает выдавать какую-то чушь. Она не находит строку (хотя она точно есть в базе). Мало того, программа, несмотря на что, по ее мнению, строки не существует, строку все-таки удаляет (!), хотя у нее нет никакой возможности для этого (у меня там стоит ловушка и весь блок кода с удалением строки должен пропускаться если строки не существует). Я понимаю, что это звучит как бред.
Я уже весь мозг себе вывихнул, пытаясь понять в чем проблема. Я начинающий программист и, конечно, думаю в первую очередь, что это я где-то накосячил. Я уже несколько дней бьюсь над этой проблемой. Ничего не могу понять и сейчас уже склоняюсь к мнению, что это глюк на самом сервере SQL.
И еще одна странность. Я все-таки могу удалять строки по одиночке, если каждый раз буду копировать строку запроса в новую вкладку браузера. Тогда все работает хорошо. Но если я пытаюсь работать в одном и том же окне браузера - одиночное удаление не проходит. А вот со множественным удалением проблем нет!
Я ничего не могу понять. Помогите дураку, пожалуйста.
Вот мой код. Я убрал оттуда некоторые функции, которые не имеют отношения к делу.
spoiler
<!DOCTYPE html>
<html>
<head>
    <title>Удаление строк</title>
    <meta charset="utf-8">
</head>
<body>
    
<?php

require_once 'L_connection.php'; // файл с данными для подключения к БД

// подключаемся к БД
$mysqli = new mysqli($host, $user, $password, $database);
if ($mysqli->connect_errno) {
    echo "<span style='color:red;'>Ошибка при открытии БД:</span> ".$mysqli->connect_error;
    exit; // завершаем программу
}
echo "Подключились к БД: ".$mysqli->host_info."<br>";

$TableName = 'Products'; // имя таблицы, с которой работаем
$nMin = 1;  // номер, с которого начинается нумерация строк в строке запроса
$idMin = 2; // id в таблице не бывает меньше этого значения

// проверяем, есть ли в строке запроса простая row (без номера)
if (filter_input(INPUT_GET, 'row', FILTER_SANITIZE_NUMBER_INT)) {
    /* Подготовка данных для удаления одной строки */
    $nMax = $nMin;      // чтобы цикл удалений сработал только один раз
    $rowGet = 'row';    // формируем имя строки без номера
}
// если простого row нет, проверяем - указано ли в строке запроса количество строк для удаления
elseif ($qRow = filter_input(INPUT_GET, 'q', FILTER_SANITIZE_NUMBER_INT)) {
    if ($qRow > 0) {
        /* Подготовка данных для множественного удаления */
        $nMax = $nMin + $qRow - 1;    // вычисляем конечный индекс
        $rowGet = "row".$nMin;        // формируем имя строки с номером
    }
    else {
        // неверно указано количество строк в строке запроса
        echo "<span style='color:red;'>Неверно указано количество строк в строке запроса: $qRow! Программа остановлена.</span><br>"; 
        closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
    } 
}
else {
    // неверный формат строки ввода
    echo "<span style='color:red;'>Неверный формат ввода в строке запроса! Программа остановлена.</span><br>"; 
    closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
}   

// считываем из строки запроса id строк для удаления и удаляем их поочередно
$i = $nMin;
while ($i <= $nMax) 
{
    // считываем id строки для удаления
    $idDel = filter_input(INPUT_GET, "$rowGet", FILTER_SANITIZE_NUMBER_INT);
    // проверяем, не является ли индекс удаляемой строки меньше минимального индекса, допустимого для таблицы
    if ($idDel < $idMin) {
        echo "<span style='color:red;'>Индекс строки для удаления указан неправильно! idDel = '$idDel' меньше idMin = $idMin. Прорамма остановлена.</span>".$mysqli->connect_error."<br>";
        closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
    }
    // подсчитываем количество строк в таблице ДО удаления
    $rowQbefore = countRows(); 
    // удаляем строку с указанным id
    delRow($idDel);
    // подсчитываем количество строк ПОСЛЕ удаления
    $rowQafter = countRows(); 
    // печатаем информацию об изменении количестве строк в таблице
    echo "<span style='color:blue;'>Количество строк в таблице ДО удаления/ПОСЛЕ удаления: $rowQbefore/$rowQafter</span><br><br>";
    
    $i++;
    $rowGet = "row".$i; // формируем новое имя строки с номером
}
    
closeDB(); // закрываем соединение с БД, выводим на экран содержимое таблицы и завершаем программу

/* Функция удаления строки из таблицы */
function delRow($delId)
{
    global $mysqli;
    global $TableName;
    $rows = -1; // для кода ошибки
   
    // проверяем, существует ли строка с таким id в таблице
    $query ="SELECT id FROM $TableName WHERE id = $delId LIMIT 1";
    
    // для этого осуществляем запрос SELECT
    if (  ( $result = $mysqli->query($query) )  ) {
        echo "<span style='color:blue;'>Запрос $query выполнен успешно.</span><br>";
        $rows = $result->num_rows; // количество строк
        $result->close(); // очищаем результирующий набор
    }
    else {
        echo "<span style='color:red;'>Ошибка при выполнении запроса $query при попытке удаления строки.</span> ".$mysqli->connect_error."<br>";
        closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
    }
    // если строка существует, то ответ на запрос должен быть 1, а если не существует - 0
    switch ($rows) {
   
    case 0:
        // строка с таким id не существует
        echo "<span style='color:red;'>Строки с id = $delId нет в таблице $TableName!</span> ".$mysqli->connect_error."<br>";
        break;
    case 1:
        // строка с таким id существует
        echo "<span style='color:blue;'>Строка с id = $delId существует в таблице $TableName.</span><br>";
          
        // формируем запрос на удаление     
        $query = "DELETE FROM $TableName WHERE id = $delId LIMIT 1";
           
        // осуществляем запрос DELETE
        if (($delResult = $mysqli->query($query))) {
            echo "<span style='color:blue;'>Запрос $query выполнен успешно.</span><br>";
            echo "<span style='color:blue;'>Cтрока с id = $delId удалена из таблицы $TableName.</span><br>";
            unset($delResult); // очищаем результирующий набор
        }
        else {
            echo "<span style='color:red;'>Ошибка при осуществлении запроса $query.</span> ".$mysqli->connect_error."<br>";
            closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
        }
        break;
    default:
        if ($rows = -1) {
            echo "<span style='color:red;'>Получен код ошибки -1! Запрос $query не удался. Программа остановлена.</span> ".$mysqli->connect_error."<br>";
        }
        else { 
            echo "<span style='color:red;'>Невероятная ошибка при попытке удаления строки. Количество строк в ответе на запрос $query = $rows.</span><br>";
        }
        closeDB(); // закрываем соединение с БД, печатаем содержимое таблицы и завершаем программу
    }
}
</body>
</html>
  • Вопрос задан
  • 2620 просмотров
Пригласить эксперта
Ответы на вопрос 6
FanatPHP
@FanatPHP
Чебуратор тега РНР
склоняюсь к мнению, что это глюк на самом сервере SQL.

всякий раз, когда ты склоняешься к такому мнению, это значит что глюк 100% в твоем собственном коде.

Учитывая весь этот адов винегрет, от которого глаза начинают кровоточить, удивительно что оно вообще хоть как-то работает.

Но в целом, главная твоя проблема состоит в том, что ты уникальный идентификатор считаешь цыферкой. которую можно складыавть, умножать, делить. А это не так.
Выкини всю эту арифметику, и всегда удаляй только ту строку, ид которой ты получил по ссылке.
Ответ написан
Комментировать
IgorPI
@IgorPI
Может ли запрос SELECT в MySql на PHP приводить к удалению данных?

Нет, не может.
Ответ написан
Комментировать
profesor08
@profesor08 Куратор тега PHP
Вот так у тебя и удаляется что-то из бд.

// приступим
$query ="SELECT id FROM $TableName WHERE id = $delId LIMIT 1";

// так так
$rows = $result->num_rows;

// оооооп
switch ($rows)

// интересно что же дальше
case 1:

// парам пам пам
$query = "DELETE FROM $TableName WHERE id = $delId LIMIT 1";


Удалять можно вот так, тебе достаточно передать список id
$mysqli->query("DELETE FROM table WHERE id IN (2, 4, 56, 654, 89569)")
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Я не специалист в MySQL но обычно транзакция заканчивается командой commit.
Проверь где ты явно завершаешь (фиксируешь транзакцию) или у тебя в свойствах соединения должен быть включен авто-коммит. Хотя авто-коммит это плохой вариант если ты удаляешь много строк.
Ответ написан
Комментировать
fl3xice
@fl3xice
Люблю что-то придумывать
Если скрипт лежит на сервере может любители sql inject(а) удаляют тебе эти данные
Ответ написан
Комментировать
@bankir1980
Думаю тут проблема как раз не в sql и скорее всего не в приведенном выше php коде. Нужно рыть в сторону кэша браузера/веб сервера (apache, nginx). Почему пишет ошибки, но при этом удаляет? Ну например, просто выполняется код 2 раза. В первый удалил, во второй - выдал ошибку. Этим можно объяснить и поведение при копировании в новую вкладку.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы