#mysql #on-duplicate-key
#mysql #on-duplicate-key
Вопрос:
Я хочу вставить значения для нескольких строк в таблицу. Кроме того, в случае дублирования запрос должен иметь возможность обновлять эти строки. Но я хочу также проверить, есть ли у пользователя доступ к записи с mytable
помощью подзапроса. Как я могу сделать это одной командой?
Не рабочий пример, потому что синтаксис вставки MySQL не поддерживает предложение WHERE:
INSERT INTO mytable (col1, col2, col3)
VALUES
(1, 2, 3),
(4, 5, 6),
(7, 8, 9)
ON DUPLICATE KEY UPDATE
col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3)
WHERE EXISTS (subquery_to_verify_if_user_can_write_into_mytable);
Для одной строки это может выглядеть следующим образом (рабочий пример, но вставка только одной строки, а не нескольких строк):
INSERT INTO mytable (col1, col2, col3)
SELECT 1, 2, 3 FROM accesstable WHERE my_condition_to_check_if_user_can_write_into_mytable LIMIT 1
ON DUPLICATE KEY UPDATE
col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3)
Но я хочу вставить значения для нескольких строк.
PS Приятно -1 в первую минуту :))
ПОСЛЕДУЮЩЕЕ РЕДАКТИРОВАНИЕ
Это уродливое решение. Создание таблицы с желаемыми значениями с помощью dumb
столбца false и объединение с поддельной таблицей, созданной путем запроса доступа пользователя:
INSERT INTO mytable (col1, col2, col3)
SELECT t1.c1, t1.c2, t1.c3
FROM (
SELECT 1 c1, 2 c2, 3 c3, 0 dumb
UNION SELECT 4, 5, 6, 0
UNION SELECT 7, 8, 9, 0
) t1
JOIN (SELECT 0 dumb FROM accesstable WHERE user_id=114 LIMIT 1) t2
ON t1.dumb=t2.dumb
ON DUPLICATE KEY UPDATE
col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3)
У кого-нибудь есть идея получше? Я совсем новичок в базах данных. Меня интересует самое простое и быстрое решение. Создание целого поддельного столбца и создание СОЕДИНЕНИЯ мне кажется довольно дорогостоящими операциями и не совсем элегантными.
УЛУЧШЕНО ПРИСОЕДИНЕНИЕ благодаря @Nick:
INSERT INTO mytable (col1, col2, col3)
SELECT t1.*
FROM ((
SELECT 1 c1, 2 c2, 3 c3
UNION SELECT 4, 5, 6
UNION SELECT 7, 8, 9
) t1
CROSS JOIN (SELECT 1 FROM accesstable WHERE user_id=114 LIMIT 1) t2)
ON DUPLICATE KEY UPDATE
col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3)
Комментарии:
1. «также иметь доступ к таблице», что именно вы подразумеваете под этим?
2. У меня есть другая таблица, в которой содержится информация о доступе для этого пользователя. Что-то вроде ‘accesstable’, содержащее информацию типа «пользователь с идентификатором x может записывать в mytable?»
3. Есть ли у вас какой-нибудь способ сделать SQL более… реально? Например, не использовать col1, col2, col3, mytable и т.д.? Каждый уровень абстракции вдали от реальной проблемы затрудняет понимание и ответ на ваш вопрос.
4. Что произошло, когда вы попробовали свой запрос?
5. @Junior обратите внимание, что дополнительный набор круглых скобок в моем запросе необходим, потому что в противном случае MySQL считает
ON DUPLICATE KEY UPDATE
, что это начало условия СОЕДИНЕНИЯ, и выдает синтаксическую ошибку, когда доходит доKEY
Ответ №1:
Лично я бы сохранил права доступа на прикладном уровне и выполнил INSERT
запрос только в том случае, если у пользователя были эти права доступа. Если вы должны делать это исключительно в MySQL, ваш последний запрос — в значительной степени ваша единственная альтернатива, хотя его можно упростить (и сделать более эффективным) с помощью a CROSS JOIN
; таким образом, вам не нужен фиктивный столбец, поскольку все строки UNION
таблицы будут автоматически присоединены к одной строке при проверке доступа (предполагая, что он возвращает данные). Примечание в моем запросе я добавил id
ключевой столбец для демонстрационных целей:
INSERT INTO mytable (id, col1, col2, col3)
SELECT t1.*
FROM ((
SELECT 2 id, 1 col1, 2 col2, 3 col3
UNION SELECT 1, 4, 5, 6
UNION SELECT 3, 7, 8, 9
) t1
CROSS JOIN (SELECT 1 FROM accesstable WHERE user_id=114 LIMIT 1) t2
)
ON DUPLICATE KEY UPDATE
col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3)
Комментарии:
1. Спасибо четырем за ваше время и усилия. ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ лучше. И да, я хочу быть уверен, что (в ТОТ момент, когда я добавляю новые данные в таблицу) у пользователя есть доступ, потому что я добавляю также его идентификатор и другие данные в mytable, и важно иметь чистые таблицы.