wpdb->prepare и MySQL UPDATE - как это делается?

19 окт. 2011 г., 20:17:30
Просмотры: 39K
Голосов: 0

Пытаюсь установить дату и время удаления в запросе плагина, но не уверен, как использовать UPDATE SET с $wpdb->prepare.

Вот мой запрос:

$cur_date = date('Y-m-d G:i:s');        
$rows_affected = $wpdb->query(
    $wpdb->prepare("
        UPDATE $table
        SET ( removed, post_id, user_id, status )
        VALUES ( %s, %d, %d, %d )
    "),
    array($cur_date, $postid, $userid, 0)
));

Могу ли я настроить UPDATE таким образом, используя $wpdb? Я совсем новичок в создании собственных запросов к БД.

Если нет, как я должен/могу это сделать?

Заранее спасибо!

РЕДАКТИРОВАНИЕ ---------------------------------------------------

Новый код:

$table = $wpdb->prefix . 'ds_entry_swoons';
$cur_date = date('Y-m-d G:i:s'); 
$rows_affected = $wpdb->query(
    $wpdb->prepare("
        UPDATE {$table}
        SET  removed = %s, post_id = %d, user_id = %d, swoon_status = %d
        WHERE post_id = $postid AND user_id = $userid;",
        $cur_date, $postid, $userid, 0
    )
);
1
Комментарии

Просто используйте внутреннюю функцию update класса wpdb. Она автоматически обрабатывает санитизацию данных за вас.

Andrew Bartel Andrew Bartel
10 янв. 2014 г. 18:14:14
Все ответы на вопрос 3
1

Существует специальный метод $wpdb->update(), который является удобным помощником для выполнения запроса UPDATE, а также выполняет санитизацию данных, вызывая $wpdb->prepare() внутренне.

10 янв. 2014 г. 15:57:54
Комментарии

Вы правы, @Rarst, исходный код wpdb::update: ... return $this->query( $this->prepare( $sql, $values ) ); : https://developer.wordpress.org/reference/classes/wpdb/update/

hamid araghi hamid araghi
2 окт. 2021 г. 14:22:22
10

Я немного исправил ваш запрос. Ему нужна таблица и условие WHERE, чтобы предотвратить изменение всех строк. Даже LIMIT 1 в конце не помешает.

$rows_affected = $wpdb->query(
    $wpdb->prepare(
        "UPDATE {$table} SET removed = %s, post_id = %d, user_id = %d, status = %d;",
        $cur_date = date('Y-m-d H:i:s'), $postid, $userid, 0
    ) // $wpdb->prepare
); // $wpdb->query

Просто добавьте WHERE... в MySQL-запрос. Правильное использование prepare:

$wpdb->prepare($format, $arg1, $arg2, ...); // аналогично printf()
19 окт. 2011 г. 21:55:27
Комментарии

LIMIT 1 в операторах UPDATE и DELETE может быть очень опасным. Особенно это актуально, если база данных является мастером в настройке репликации MySQL, потому что нет гарантии порядка выполнения UPDATE/DELETE на реплике. Предупреждения об этом будут записаны в журнал ошибок MySQL на мастере. В остальном ваш ответ по сути верен, как только @dkmojo добавит условие WHERE. +1 !!!

RolandoMySQLDBA RolandoMySQLDBA
19 окт. 2011 г. 22:28:32

Если вы указываете первичный ключ ID или комбинацию уникальных ключей... почему это было бы опасно?

EarnestoDev EarnestoDev
19 окт. 2011 г. 22:32:52

Это было бы единственным исключением. С неуникальными ключами ситуация была бы иной. MySQL все равно может записывать предупреждения в журнал ошибок в любом случае.

RolandoMySQLDBA RolandoMySQLDBA
19 окт. 2011 г. 22:35:07

Я даже написал пост об этом в DBA StackExchange: http://dba.stackexchange.com/questions/1371/problem-with-mysql-subquery/1384#1384. Это связано с тем, как MySQL Optimizer выполняет преобразования запросов под капотом.

RolandoMySQLDBA RolandoMySQLDBA
19 окт. 2011 г. 22:37:53

Верно, но это должно быть осознанным решением. Если вы знаете, что планируете обновить одну запись, насколько мне известно, хорошей практикой является установка LIMIT 1. Если у вас переменное количество записей для обновления, никогда не используйте LIMIT, так как сортировка по умолчанию... не отсортирована :)

EarnestoDev EarnestoDev
19 окт. 2011 г. 22:44:10

На сайте MySQL есть багрепорты для версий 4.0 (закрыт: http://bugs.mysql.com/bug.php?id=1024) и 5.1 (патч применён год назад: http://bugs.mysql.com/bug.php?id=42415) относительно использования UPDATE/DELETE с LIMIT. Даже со всеми исправлениями багов вокруг LIMIT, репликация MySQL на Slave-сервере всё ещё может пострадать. Я узнал об этом просто из порядка SELECT-записей: http://dba.stackexchange.com/q/6051/877.

RolandoMySQLDBA RolandoMySQLDBA
19 окт. 2011 г. 22:58:57

Использование LIMIT также может включать временные таблицы, если запрос этого требует. Все временные таблицы, создаваемые запросами, по своей природе не отсортированы, как вы уже отмечали ранее. LIMIT проходит через такие временные таблицы, из-за чего порядок выполнения и доступа отличается между Master и Slave.

RolandoMySQLDBA RolandoMySQLDBA
19 окт. 2011 г. 23:03:42

Спасибо за подробный отзыв! Я добавил условие WHERE и разместил отредактированный код выше. Но не уверен, для чего нужны фигурные скобки '{}' вокруг $table и нужны ли они вообще. В других моих запросах они не используются. Для чего нужны '{}'? Ещё раз спасибо!

dkmojo dkmojo
20 окт. 2011 г. 19:00:53

@dkmojo {$variable} — это правильный способ использования переменных в "строках" для полного контроля и избежания нежелательных символов при парсинге. (Читайте здесь)[http://php.net/manual/en/language.types.string.php]. Ознакомьтесь с разделами Простой синтаксис и Сложный (фигурный) синтаксис (найдите в тексте на указанной странице). (Например: $table = "{$wpdb->prefix}ds_entry_swoons";)

EarnestoDev EarnestoDev
20 окт. 2011 г. 19:07:44

круто, спасибо за разъяснение и ссылку. Я видел их раньше в коде плагинов, но не был уверен в их назначении. Теперь я знаю, а знать — это уже половина победы (GI JOE — не удержался) :)

dkmojo dkmojo
20 окт. 2011 г. 21:51:33
Показать остальные 5 комментариев
0

Вы можете вставить столько переменных, сколько нужно (%d для цифр, %s для строк ...)

global $wpdb;
$zz = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta 
    SET meta_value = '%s'       WHERE post_id = '%d'    OR WHERE post_id = '%d' ", 
                      $value,                    $id_1,                     $id_2   ) );
var_dump($zz); exit;
21 июл. 2015 г. 20:54:32