MySQL INSERT несколько строк на DUPLICATE KEY UPDATE ... WHERE EXISTS (подзапрос) - PullRequest
0 голосов
/ 13 апреля 2019

Я хочу вставить значения для нескольких строк в таблицу. Кроме того, в случае дублирования запрос должен иметь возможность обновлять эти строки. Но я также хочу проверить, есть ли у пользователя доступ для записи в mytable с использованием подзапроса. Как я могу сделать это одной командой?

Пример не работает, потому что MySQL INSERT синтаксис не поддерживает предложение 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 и соединение с поддельной таблицей, сделанной из опроса для доступа пользователя:

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)

У кого-нибудь есть идея получше? Я довольно новичок в базах данных. Меня интересует самое простое и быстрое решение. Создание целого поддельного столбца и создание JOIN мне кажется довольно дорогими и не совсем элегантными операциями.

УЛУЧШЕНО ПРИСОЕДИНЯЙТЕСЬ спасибо @ Ник:

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 Ответ

1 голос
/ 14 апреля 2019

Лично я бы сохранял права доступа на уровне приложений и выполнял запрос INSERT , только если пользователь имел эти права доступа. Если вы должны делать это исключительно в MySQL, ваш последний запрос в значительной степени является вашей единственной альтернативой, хотя его можно упростить (и сделать более эффективным) с помощью 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)

Демонстрация по dbfiddle

...