Запрос API базы данных Drupal - row.update, если существует, иначе row.insert - PullRequest
3 голосов
/ 29 апреля 2011

Я пытался запустить запрос в drupal, который обновит записи, если они уже существуют, или вставит новую, если это не так. Код выглядит следующим образом:

db_query("IF EXISTS (SELECT %d FROM {uc_posten_packages.pid})
UPDATE {uc_posten_packages} SET title = '%s', label = '%s', cost = '%d', length = '%d', width ='%d', height = '%d', weight = '%d'  WHERE pid = %d
ELSE
INSERT INTO {uc_posten_packages} VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d')",$id, $title, $label, $rate, $length, $width, $height, $weight, $id, $id, $title, $label, $rate, $length, $width, $height, $weight);

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

...near 'IF EXISTS (SELECT 1 FROM uc_posten_packages.pid) UPDATE uc_posten_packages ' at line 1 query:
IF EXISTS (SELECT 1 FROM uc_posten_packages.pid) UPDATE uc_posten_packages SET title = 'vfbv', label = 'bbv', cost = '22', length = '232', width ='22', height = '22', weight = '22' WHERE pid = 1 ELSE INSERT INTO uc_posten_packages VALUES ('1', 'vfbv', 'bbv', '22', '232', '22', '22', '22')

Должен ли этот запрос работать и / или есть ли лучший способ справиться с этим в drupal?

Ответы [ 4 ]

6 голосов
/ 09 апреля 2013

То, что вы ищете, сердечно называется «upsert» (обновление вставьте в противном случае), и для этого есть функция drupal: db_merge. Хорошая запись здесь: http://drupal.org/node/310085

drupal_write_record () не выполняет автоматически "upsert". Он всегда либо вставляет, либо обновляет в зависимости от того, что вы передаете, но не оба одновременно.

4 голосов
/ 29 апреля 2011

[ОБНОВЛЕНИЕ Янв 2013]

Этот ответ относится к более старой версии Drupal, чем текущая стабильная версия. Отредактируйте этот ответ, добавив в него раздел обновления с более актуальной информацией, поскольку я больше не работаю с Drupal и не слежу за изменениями в его API.

-semperos

[/ ОБНОВЛЕНИЕ январь 2013]

У вас есть несколько вариантов, а именно drupal_write_record или выполнение примера запроса и проверка результатов. Это не должно быть сделано в одном запросе SQL, как в вашем вопросе.

drupal_write_record (предпочтительный метод)

Функция drupal_write_record позволяет вам указать таблицу, с которой вы хотите иметь дело, и объект (или связанный массив), который содержит данные для каждого столбца / поля этой таблицы. Если у вас уже есть первичный ключ для строки, которую вы пытаетесь обновить, вы включаете его в качестве третьего параметра функции, и drupal_write_record автоматически использует команду SQL UPDATE. В противном случае значение по умолчанию INSERT. Например:

drupal_write_record('uc_posten_packages', array('title'  => "Foobar",
                                      'label'  => "foobar",
                                      'cost'   => 10,
                                      'length' => 100,));

Это будет INSERT новая запись с этой информацией. Если бы вы включили третий аргумент array($pid), где $pid - это имя поля, которое выступает в качестве первичного ключа для таблицы, вместо этого было бы выполнено обновление.

Эта функция будет работать только в том случае, если таблица, с которой вы имеете дело, была определена с использованием hook_schema, что должно быть справедливо для любого правильно разработанного модуля Drupal, имеющего таблицы базы данных. Поскольку эта функция использует схему для обеспечения правильной записи в базу данных, следует использовать эту функцию, когда это возможно (или когда не существует других более специфических функций, например, node_save для узловых объектов).

Тестовый запрос

Вы можете просто запустить пример запроса, используя db_result(db_query("SELECT...")). Если результат не найден, он возвращает пустую строку, которая в PHP оценивается как false, поэтому ваш код может выглядеть следующим образом:

if (db_result(db_query("SELECT * FROM {uc_posten_packages} WHERE pid = %d", $pid))) {
  // UPDATE
} else {
  // INSERT
}
1 голос
/ 26 февраля 2016

Согласно drupal_write_record операция была UPDATE или INSERT, вам нужно знать, существовала запись или нет, прежде чем совершать транзакцию. Это не то, что делает drupal_write_record (). Эта функция просто проверяет свои аргументы и выдает обновление или вставку соответственно. Таким образом, на самом деле не может определить, была ли функция INSERT или UPDATE.

Решение использует запрос db_merge () , это относительно новый стандарт SQL ANSI, который делает именно то, что мне нужно (а в случае MySQL это делает в атомарной транзакции).

$return_value = db_merge('mytable')
            ->key(array('id' => $key))
            ->fields($fields)
            ->updateFields(array(
                'updatedon' => $now,
            ))
            ->execute();

Возвращаемое значение - целое число, возвращающее 1 для вставок и 2 для обновлений.

0 голосов
/ 29 апреля 2011

Это глупый пример синтаксиса замены.

mysql> create table test (
    -> id int,
    -> a int,
    -> b int,
    -> unique (id)
    -> ) engine = myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> replace into test (id,a,b) values (1,4,2);
Query OK, 1 row affected (0.00 sec)

mysql> replace into test (id,a,b) values (2,10,3);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+------+------+
| id   | a    | b    |
+------+------+------+
|    1 |    4 |    2 |
|    2 |   10 |    3 |
+------+------+------+
2 rows in set (0.00 sec)

mysql> replace into test (id,a,b) values (1,5,5);
Query OK, 2 rows affected (0.00 sec)

mysql> select * from test;
+------+------+------+
| id   | a    | b    |
+------+------+------+
|    1 |    5 |    5 |
|    2 |   10 |    3 |
+------+------+------+
2 rows in set (0.00 sec)

Надеюсь, он вам поможет.

...