php - обновить оператор sql с несколькими строками

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

Это мой код:

$body = file_get_contents('php://input');
$jsonArray = json_decode($body, true);

$sql = array();
foreach ($jsonArray as $row) {   

    $sql[] = '("'.$row['firstname'].'", "'.$row['lastname'].'", "'.$row['sex'].'", "'.$row['dateOfBirth'].'", "'.$row['email'].'")';

}

$column_name = "(firstname, lastname, sex, dateOfBirth, email)";
$stringImplode = implode(',', $sql);

$action = $mysqli->query('INSERT INTO tbl_syncList '. $column_name .' VALUES '.$stringImplode .'ON DUPLICATE KEY UPDATE XXXXXXX'); // --> I get stuck here

Я не знаю, как мне писать после ON DUPLICATE KEY UPDATE: я знаю, что это должно быть что-то вроде «имя_столбца = значение1, имя_столбца2 = значение2...», но можно ли использовать приведенные выше массивы таким образом, как «( имя_столбца1, имя_столбца2...) = (значение1, значение2...) что могло бы быть полезно, если бы я добавил несколько атрибутов?

Поскольку это находится вне цикла, я не уверен, как ссылаться на мое значение внутри массива sql[], поскольку у меня может быть много разных значений для одного и того же имени столбца.

Кроме того, я хотел бы добавить предложение WHERE в конце с чем-то вроде «WHERE timestamp_column_name ‹ timestamp_value», но я не знаю, возможно ли это.

Если бы кто-нибудь мог помочь мне решить эту проблему, это было бы здорово.


person Trichophyton    schedule 20.02.2016    source источник


Ответы (1)


Чтобы ответить на ваш первый вопрос, вы можете использовать VALUES() в операторе ON DUPLICATE KEY UPDATE:

$action = $mysqli->query('INSERT INTO tbl_syncList '. $column_name .' VALUES '.$stringImplode .'ON DUPLICATE KEY UPDATE firstname = VALUES(firstname), lastname = VALUES(lastname), sex = VALUES(sex), dateofbirth = VALUES(dateofbirth), email = VALUES(email)');

Однако я не думаю, что ваша вторая проблема может быть решена с использованием этого подхода. Я бы рекомендовал сначала вставить все записи в промежуточную таблицу, которая не имеет каких-либо уникальных ограничений для столбцов, которые вы вставляете/обновляете. Затем используйте дополнительные запросы (или, что предпочтительнее, процедуру базы данных) для выполнения отдельных запросов на обновление и вставку на основе соединения между таблицами и любых других критериев, которые у вас есть.

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

UPDATE a
SET a.firstname = b.firstname,
    a.lastname  = b.lastname,
    a.sex       = b.sex,
    ...
FROM stagingtable b
JOIN tbl_syncList a ON a.idcolumn = b.idcolumn
WHERE b.timestamp > a.timestamp

INSERT tbl_syncList(firstname, lastname, sex, dateOfBirth, email)
SELECT 
    b.firstname,
    b.lastname,
    b.sex,
    b.dateOfBirth,
    b.email
FROM stagingtable b
LEFT JOIN tbl_syncList a ON a.idcolumn = b.idcolumn
WHERE a.idcolumn IS NULL
person UberDoodles    schedule 20.02.2016
comment
Спасибо попробую! - person Trichophyton; 21.02.2016
comment
Вы правы, я не могу использовать тот же подход для обновления данных. Но я не понимаю, почему он не может работать с условием WHERE следующим образом: ON DUPLICATE KEY UPDATE firstname = VALUES(firstname), ... WHERE timestamp (т.е. имя_столбца базы данных) ‹ VALUES(lastModification) ), т.е. строка, содержащая дату последнего изменения'); Потому что относительно близкий оператор [SELECT * from tbl_syncList WHERE timestamp ‹ lastModification] работает, когда применяется как один запрос sql... Оператор UPDATE управляет вещами так по-другому? - person Trichophyton; 22.02.2016
comment
Я не уверен, что понимаю, что такое таблица «a» в вашем примере, это мой tbl_syncList происхождения? Или столов больше двух? - person Trichophyton; 22.02.2016
comment
Извините, я пытался, но я не уверен, что все понимаю даже после прочтения документации. - person Trichophyton; 22.02.2016
comment
Тот факт, что вы не можете использовать предложение WHERE в предложении ON DUPLICATE KEY UPDATE, является лишь одним из тех раздражающих случаев, когда легко увидеть, как небольшая дополнительная функциональность может сделать вашу жизнь намного проще, но эта небольшая функциональность еще не разработан. «a» в моем примере — это псевдоним «tbl_syncList», а «b» — это псевдоним «stagingtable». См. techonthenet.com/mysql/alias.php. - person UberDoodles; 22.02.2016
comment
Верно :-). Я понимаю ваш псевдоним, но не уверен, содержит ли ваш код два шага или более. Я не вижу, если вы 1) обновите tbl_syncList (псевдоним a) с помощью процедуры FROM-JOIN-WHERE с элементами моей промежуточной таблицы (в этом случае я могу понять предложение WHERE), а затем 2) вы добавите (процедура INSERT) столбцы, которые не были обновлены (это должно соответствовать idcolumn IS NULL). --- или если вы 1) обновляете только tbl_syncList (но я бы не знал почему), то 2) ПРИСОЕДИНЯЙТЕСЬ к таблицам (но в этом случае они будут почти одинаковыми) и 3) ВСТАВЛЯЕТЕ элемент. Как вы думаете, вы могли бы просто помочь мне немного больше? - person Trichophyton; 23.02.2016
comment
Это первый описанный вами случай. Оператор обновления обновляет все записи в tbl_synclist, которые существуют в обеих таблицах и имеют более позднюю отметку времени в промежуточной таблице. Затем оператор вставки вставляет любые записи из промежуточной таблицы в tbl_synclist, где их еще нет в tbl_synclist. - person UberDoodles; 23.02.2016
comment
Спасибо большое очень понятно! И (последний вопрос), если бы я сохранил старую запись (скажем, A) в [tbl_a] и добавил (ранее ту же) запись, которая была изменена за это время из [tbl_b] (скажем, A') (т.е. вместо обновления A-›A' я хотел бы A+A'), я должен просто удалить оператор WHERE, и в конце [tbl_a] у меня будет: 1) все записи, которые уже были вставлены при предыдущей синхронизации (например, A+B+C) и 2) вставка тех предыдущих записей, которые были обновлены за это время (скажем, B'+C'). Я хотел бы убедиться, что нет повторяющихся строк (например, A+A+A'+B+B+B' и т. д.). Верно? - person Trichophyton; 24.02.2016
comment
Или есть другой способ получить только новые и обновленные (›timestamp) записи из stagingTable (b) в виде INSERTED строк в tbl_syncList (a) и ничего не делать, когда записи похожи? - person Trichophyton; 25.02.2016
comment
Что-то вроде удаления первой процедуры обновления и сохранения только второй путем добавления в оператор WHERE a.column IS NULL OR b.timestamp › a.timestamp? Подводя итог: ВСТАВЬТЕ a... ВЫБЕРИТЕ b.firstname/lastname... FROM b... LEFT JOIN a ON... ГДЕ a.idcolumn IS NULL OR b.timestamp › a.timestamp? Имеет ли это смысл? - person Trichophyton; 25.02.2016