Как обновить неуникальный столбец, если строка существует, иначе обновить другую строку в [MySQL]? - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь построить запрос к UPDATE строке, если она существует, либо обновить другую строку. Я хочу обновить только одну строку каждый раз, когда выполняется запрос. Второй WHERE предназначен для случая, когда нет возврата из первой части запроса.

Я хочу обновить один атрибут со значением по умолчанию 'null'. Нет способа использовать открытый ключ, как я видел в других постах ( например, ).

Я могу вернуть нужный кортеж с помощью UNION, но затем не могу преобразовать выражение в запрос UPDATE, как требуется:

(SELECT * FROM table
  WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1)
UNION
(SELECT * FROM table 
  WHERE column='null' LIMIT 1)
LIMIT 1;

Кажется, это всегда возвращает первое WHERE, если существует, а второе WHERE.

Я получаю синтаксические ошибки при попытке создать IF-ELSE на основе переменной count:

SET @count=(SELECT COUNT(*) FROM table 
              WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1);
IF @count THEN
  (UPDATE table SET column='foobar'
  WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1);
ELSE
  (UPDATE table SET column='foobar'
  WHERE column='null' LIMIT 1);
END IF;

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

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

Любая помощь очень ценится!

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

Вот один из способов сделать это. Запустите первое ОБНОВЛЕНИЕ. После этого функция ROW_COUNT() вернет либо 0, либо 1, в зависимости от того, повлияло ли первое ОБНОВЛЕНИЕ на какие-либо строки.

Во втором ОБНОВЛЕНИИ сделайте изменение запретом, установив столбец = столбец, если ROW_COUNT() указывает, что первое ОБНОВЛЕНИЕ что-то изменило.

UPDATE table SET column='foobar' WHERE (foo) AND (bar) AND column='null' LIMIT 1;
UPDATE table SET column=IF(ROW_COUNT()=1,column,'foobar') WHERE column='null' LIMIT 1;

Однако обратите внимание, что ROW_COUNT () возвращает 0, если первые UPDATE совпали со строками, но не вносили никаких изменений, поскольку в найденных строках уже было значение 'foobar'.

0 голосов
/ 28 июня 2018

Если я правильно понимаю, вы можете просто использовать order by и limit:

update table
    set . . . 
    where column = 'null'
    order by ((foo) AND (bar)) desc
    limit 1;

desc в первую очередь поместит строки, соответствующие двум условиям. Затем последуют другие строки. limit выбирает первый матч.

Думаю, я бы более склонен заказывать два условия по отдельности:

order by (foo) desc, (bar) desc
0 голосов
/ 28 июня 2018

Как то так? Я не могу обещать, что это быстро:

update <table>
where
    column is null and <foo> and <bar>
    or not (<foo> and <bar>) and not exists (
        select 1 from <table> where column is null and <foo> and <bar>
    );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...