MySql - 多表 - AND 不是正确的选择,但什么是?

MySql - Multitable - AND is not the correct choice, but what is?

我有两个 table:

我的table1

UserId (int) (primary_key)
Save (blob)

我的table2

UserId (int) (primary_key)
Save (blob)

我执行以下 mysql 命令:

 UPDATE mytable1 tb1, mytable2 tb2 SET tb1.Save='', tb2 .Save='' WHERE tb1.UserId=25 AND dbSv1.UserId=25

当两个 table 都有一个 UserId = 25 的用户时,这会起作用并且保存设置为“”。但是,如果一个 table 没有 UserId = 25 的用户,而另一个有,则 Save 不会在有的用户中设置为 ''。这不是我想要的行为。

OR 不是要使用的东西,因为其他保存将设置为 '',其 UserId 不为 25。那么我需要什么?

您的查询使用老式逗号语法进行连接操作。 (SQL 中存在一些问题...... dbSv1 用作限定符,但它不会显示为 table 名称或 table 别名。我们假设应该是 tb2.

您的查询等同于:

  UPDATE mytable1 tb1
    JOIN mytable2 tb2
     SET tb1.save=''
       , tb2.save=''
   WHERE tb1.userid=25
     AND tb2.userid=25

如果在 tb1tb2 中都没有找到匹配的行,则 JOIN 操作将生成一个空集。这是预期的行为。

考虑从这个查询 return 编辑的结果集:

  SELECT tb1.userid
       , tb2.userid
    FROM mytable1 tb1
    JOIN mytable2 tb2
   WHERE tb1.userid=25
     AND tb2.userid=25

当 tb2 中没有满足谓词的行时,查询将不会 return 任何行。

您可以使用 "outer" 联接使来自 table 之一的 returning 行成为可选行。例如,即使 mytable2...

中不存在匹配的行,也要更新 mytable1
  UPDATE mytable1 tb1
    LEFT
    JOIN mytable2 tb2
      ON tb2.userid=25 
     SET tb1.save=''
       , tb2.save=''
   WHERE tb1.userid=25

如果 mytable1 中没有 userid=25 的行,则不会更新任何行。

MySQL 不支持 FULL OUTER JOIN。但是你尝试这样的事情,使用内联视图 return 一行,然后对 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 = ''

SQL小提琴演示:http://sqlfiddle.com/#!9/6f8598/1


跟进

一个"join"是一个普通的SQL操作。您应该可以轻松找到有关它的功能的信息。

“+ 0”并非绝对必要。 MySQL 中的 shorthand 转换为数字很方便。作为测试,请查看 MySQL return 的内容:

SELECT '25' + 0
     , '25xyz' + 0
     , 'abc' + 0 

内联视图的目的是 return 单行。我们本可以编写查询以对 user_id 进行两次硬编码,并忽略从行视图中编辑的 return ....

 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 = ?

我们有点 "lose" 这两个值相同的想法。为了只指定一次硬编码值,我有内联视图 return 我们想要在外部连接的 ON 子句中 "match" 的值。

 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

现在我的意图更明确了...我正在寻找 "one" user_id 值。添加“+ 0”表示无论传入什么值(例如“25”、'foo' 或其他),我的语句都会将其解释为数值。

内联视图

我用了 "inline view" 这个词。这只是在我们通常有 table 的上下文中使用的 SELECT 查询。

例如如果我有一个名为 mine 的 table,我可以编写一个查询...

  SELECT m.id, m.name FROM mine m

对其进行测试并查看它 return 行,yada,yada。

我也可以这样做:将该查询包装在括号中并在另一个语句中 代替 table 的 引用它,就像这样...

  SELECT t.*
    FROM ( SELECT m.id, m.name FROM mine m ) t

MySQL 要求我们为其分配一个别名,就像我们可以为 table 做的那样。我们称其为 内联视图 ,因为它类似于我们用于 存储视图 的模式。让我们看一下这样做的演示。

(这只是该模式的演示;出于某些原因我们不想这样做。)

  CREATE VIEW myview
  AS
  SELECT m.id, m.name FROM mine m
  ; 

那么我们可以这样做:

  SELECT t.* FROM myview t

使用 内联视图 我们遵循相同的模式,但我们绕过了单独的 create view 语句。 (这是一个导致隐式提交并创建数据库对象的 DDL 语句。)绕过它,我们有效地创建了一个仅存在于语句上下文中的视图,并在语句中执行 "inline" .

  SELECT t.* FROM ( SELECT m.id, m.name FROM mine m ) t

MySQL 文档将内联视图称为 "derived table"。如果我们(不小心)忘记了别名,我们返回的错误会显示类似 "every derived table must have a alias" 的内容。用于 MySQL 以外的数据库的更通用的术语是 "inline view"。