Обновление PDO MYSQL, только если отличается

У меня есть веб-программа, которая позволяет администратору обновлять информацию пользователя... При этом я хочу, чтобы обновлялись только столбцы, которые действительно были "обновлены"...

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

Может кто-нибудь, пожалуйста, помогите мне с заявлением?

По сути в psuedocode:Update FIRSTNAME if $editedUserdata['firstname'] != FIRSTNAME, LASTNAME if $editedUserData['lastname']! = LASTNAME... и т.д...

Вот что у меня есть для почтового индекса...

        $password = sha1($password);
        $editedUserData = array(
              'firstname' => $firstname,
              'lastname' => $lastname,
              'username' => $username,
              'password' => $password,
              'cellphone' => $cellphone,
              'security_level' => $seclvl,
              'email' => $email,
              'direct_phone' => $direct,
              'ext_num' => $extension,
              'is_active' => $userflag
            );

Тогда это должно быть что-то вроде

$query = $this->db->prepare('UPDATE FIRSTNAME if(?) IS NOT FIRSTNAME, LASTNAME if(?) IS NOT LASTNAME, USERNAME if (?) IS NOT USERNAME.... VALUES (:firstname, :lastname, :username).....'

if ($query -> execute($editedUserData)) {
    more code....

4 ответа

Решение

Возможно, я не понимаю проблему, которую вы пытаетесь решить, но вам не нужно проверять, изменилось ли значение поля.

Если значение поля равно "A" и вы поставили "A", оно останется прежним, в противном случае, если вы добавите "B", оно будет обновлено, как и ожидалось

Готовое заявление будет что-то вроде

$stmt = $dbh->prepare("
    UPDATE table_name
    SET
        field1 = :value1,
        field2 = :value2
    WHERE
        field0 = :key
");

$stmt->bindParam(':value1', $value1, PDO::PARAM_STR);
$stmt->bindParam(':value2', $value2, PDO::PARAM_STR);
$stmt->bindParam(':key', $key, PDO::PARAM_INT);

$stmt->execute()

Согласно документации MySQL - ссылка: ( http://dev.mysql.com/doc/refman/5.0/en/update.html)

"Если вы установите для столбца значение, которое он имеет в данный момент, MySQL заметит это и не обновит его".

Запустите один оператор, чтобы обновить строку.

Во-первых, какой уникальный идентификатор строки в users таблица, есть ли уникальный userid или же username? Вам понадобится предложение WHERE в операторе UPDATE, чтобы обновлялась только эта строка.

Нормативный шаблон для оператора UPDATE для обновления нескольких столбцов в одной строке выглядит следующим образом:

UPDATE users
   SET col2 = 'value'
     , col3 = 'another value'
     , col4 = 'fi'
 WHERE idcol = idvalue ;

Чтобы использовать подготовленный оператор с PDO, текст SQL может выглядеть примерно так, если вы используете именованные заполнители:

UPDATE users
   SET col2 = :col2_value
     , col3 = :col3_value
     , col4 = :col4_value
 WHERE idcol = :id_value

Или это, если вы используете позиционную нотацию для заполнителей:

UPDATE users
   SET col2 = ?
     , col3 = ?
     , col4 = ?
 WHERE idcol = ?

(Мое личное предпочтение - использовать именованные заполнители, а не позиционные, но любой из них будет работать.)

Вот как я это сделаю, запустив подготовку, затем bind_param, а затем выполнить.

$sql = "UPDATE users
           SET col2 = :col2_value
             , col3 = :col3_value
             , col4 = :col4_value
         WHERE idcol = :id_value ";

$stmt = $dbh->prepare($sql);
$stmt->bindParam(':col2_value', $col2_val, PDO::PARAM_STR);
$stmt->bindParam(':col3_value', $col3_val, PDO::PARAM_STR);
$stmt->bindParam(':col4_value', $col4_val, PDO::PARAM_STR);
$stmt->bindParam(':id_value'  , $id_val, PDO::PARAM_STR);
$stmt->execute();

Чтобы сделать что-то другое, динамически создать текст SQL и настроить вызовы bindParam, это добавит ненужную сложность к коду. Для этого нет никакого преимущества в производительности; когда выполняется этот оператор UPDATE, MySQL должен заблокировать строку и сохранить новую копию строки. На самом деле он ничего не сохраняет (кроме нескольких байтов передачи данных), чтобы избежать отправки значения столбца, которое не изменилось.

Если вы действительно хотите использовать случаи, прочитайте это.

Нет причин делать это в вашем случае, как указано в комментариях @spencer7593:

Это НАМНОГО больше накладных расходов... обходы базы данных, анализ оператора, разработка плана выполнения, выполнение оператора, получение блокировок, возвращение статуса, проверка состояния клиентом и т. Д. Это просто кажется неэффективным подходом.

Я предполагаю, что любая СУБД достаточно умна, чтобы заметить, что кэши и т. Д. Не должны пересчитываться (если ничего не меняется), если в этом проблема.

Другие вопросы по тегам