В вашем запросе используется синтаксис синтаксиса старой школы для операции соединения. (Есть некоторые проблемы в SQL ... dbSv1
используется как определитель, но он не отображается как псевдоним таблицы или таблицы. Предполагается, что это должно быть tb2
.
Ваш запрос эквивалентно:
UPDATE mytable1 tb1
JOIN mytable2 tb2
SET tb1.save=''
, tb2.save=''
WHERE tb1.userid=25
AND tb2.userid=25
Если соответствующая строка не найдена в любом tb1
или tb2
, на операцию JOIN будет производить пустое множество Это ожидаемое поведение
Рассмотрим результирующий набор, возвращаемый из этого.. запрос:
SELECT tb1.userid
, tb2.userid
FROM mytable1 tb1
JOIN mytable2 tb2
WHERE tb1.userid=25
AND tb2.userid=25
Если в tb2 нет строк, удовлетворяющих предикатам, запрос не будет возвращать никакие строки.
Вы можете использовать «внешнее» соединение, чтобы сделать возвращаемые строки из одной из таблиц необязательными. Например, чтобы обновить mytable1
даже если нет соответствующих строк не существует в mytable2
...
UPDATE mytable1 tb1
LEFT
JOIN mytable2 tb2
ON tb2.userid=25
SET tb1.save=''
, tb2.save=''
WHERE tb1.userid=25
Если нет строки в mytable1
, которые имеют идентификатор пользователя = 25, то это не будет обновлять какие-либо строки.
MySQL не поддерживает FULL OUTER JOIN
. Но вы пытаетесь что-то вроде этого, используя вложенное вернуть строку, а затем выполнять внешние соединения и к mytable1 и mytable2 ...
UPDATE (SELECT 25 + 0 AS userid) i
LEFT
JOIN mytable1 tb1
ON tb1.userid = i.userid
LEFT
JOIN mytable2 tb2
ON tb2.userid = i.userid
SET tb1.save = ''
, tb2.save = ''
SQLFiddle демонстрация: http://sqlfiddle.com/#!9/6f8598/1
Followup
«Соединение» - это обычная операция SQL. Вам не должно быть никаких проблем с поиском информации о том, что это такое.
«+ 0» не является абсолютно необходимым. Это удобный сокращенный код в MySQL для CAST для численного.В качестве теста, посмотрим, что возвращает MySQL для этого:
SELECT '25' + 0
, '25xyz' + 0
, 'abc' + 0
Целью зрения инлайн было возвращать одну строку. Мы могли бы написать запрос, чтобы жестко закодировать user_id два раза, и игнорировать то, что вернулись с точки зрения линии ....
SELECT t1.user_id AS t1_user_id
, t2.user_id AS t2_user_id
FROM (SELECT 'foo' AS dontcare) i
LEFT
JOIN mytable1 t1
ON t1.user_id = 25
LEFT
JOIN mytable t2
ON t2.user_id = 25
Я предпочитаю, чтобы сделать его более ясным, что наша цель для обоих значений быть одинаковым. Мы могли бы указать, где один из них - 23, а другой - 27. Это синтаксически справедливо для этого. Когда мы превращаем это в подготовленное заявление с связываемых заполнителей ...
SELECT t1.user_id AS t1_user_id
, t2.user_id AS t2_user_id
FROM (SELECT 'foo' AS dontcare) i
LEFT
JOIN mytable1 t1
ON t1.user_id = ?
LEFT
JOIN mytable t2
ON t2.user_id = ?
Мы вроде «потерять» идею, что эти два значения одинаковы. Чтобы получить это жестко заданное значение, указанное только один раз, у меня есть встроенный вид, возвращающий значение, которое мы хотим «сопоставить» в предложении ON внешних соединений.
SELECT t1.user_id AS t1_user_id
, t2.user_id AS t2_user_id
FROM (SELECT ? AS user_id) i
LEFT
JOIN mytable1 t1
ON t1.user_id = i.user_id
LEFT
JOIN mytable t2
ON t2.user_id = i.user_id
Теперь мое намерение более ясное ... Я ищу «одно» значение user_id. Добавление «+ 0» означает, что любое значение передается (например, «25», «foo» или что-то еще), мой оператор будет интерпретировать это как числовое значение.
рядный вид
Я использовал термин "встроенный вид". Это просто запрос SELECT, используемый в контексте, где у нас обычно есть таблица.
например. если у меня есть таблица с именем mine
, я могу написать запрос ...
SELECT m.id, m.name FROM mine m
тест и посмотреть, что он возвращает строки, болтовня, болтовня.
Я также могу это сделать: обернуть этот запрос в круглые скобки и ссылаться на него вместо таблицы в другом заявлении, как это ...
SELECT t.*
FROM (SELECT m.id, m.name FROM mine m) t
MySQL требует, чтобы мы присвоить псевдоним, который , как мы можем это сделать, если бы это была таблица. Мы называем это inline view, потому что он похож на шаблон, который мы используем для сохраненного вида. Давайте посмотрим на демонстрацию этого.
(Это просто демонстрация картины, есть несколько причин, мы не хотели бы, чтобы это сделать.)
CREATE VIEW myview
AS
SELECT m.id, m.name FROM mine m
;
Тогда мы можем сделать это:
SELECT t.* FROM myview t
С inline view мы следуем одному и тому же шаблону, но мы обходим отдельный оператор create view
. (Это заявление DDL, которое вызывает неявное коммитирование и создание объекта базы данных.) Обходя это, мы фактически создаем представление, которое существует только в контексте инструкции и делает это «inline» внутри оператора.
SELECT t.* FROM (SELECT m.id, m.name FROM mine m) t
Документация MySQL относится к встроенному представлению как к «производной таблице».Если мы (случайно) забыли псевдоним, ошибка, которую мы вернем, говорит что-то вроде «каждая производная таблица должна иметь псевдоним». Более общий термин, используемый для баз данных, отличных от MySQL, - это «встроенный просмотр».
Поместить 2 оператора в транзакцию – Mihai
Как вы это делаете с помощью одного оператора mysql? (Я знаю, как это сделать с множественным вызовом mysql в php, но предпочел бы избежать этого и сделать один вызов mysql.) – Rewind
Вы не можете сделать это в одном заявлении sql. Но большинство расширений mysql поддерживают выделение нескольких операторов sql в одном вызове. Но если вы используете транзакции, на самом деле не имеет значения, сколько звонков вы совершаете. – Shadow