MySql - Multitable - AND不是正确的选择,但它是什么?

时间:2016-04-08 20:06:22

标签: mysql logic

我有两张桌子:

MYTABLE1

UserId (int) (primary_key)
Save (blob)

mytable2

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

当两个表都有UserId = 25的用户时,这样就可以了,Save设置为''。但是,如果一个表没有UserId = 25的用户,但另一个表没有,那么Save就不会设置为''。这不是我想要的行为。

OR不是要使用的东西,因为其他保存将被设置为''没有UserId为25.所以我需要什么?

1 个答案:

答案 0 :(得分:2)

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

您的查询相当于:

tb2

如果在 UPDATE mytable1 tb1 JOIN mytable2 tb2 SET tb1.save='' , tb2.save='' WHERE tb1.userid=25 AND tb2.userid=25 tb1中找不到匹配的行,则JOIN操作将生成一个空集。这是预期的行为。

考虑从此查询返回的结果集:

tb2

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

您可以使用“外部”连接使其中一个表的返回行可选。例如,即使 SELECT tb1.userid , tb2.userid FROM mytable1 tb1 JOIN mytable2 tb2 WHERE tb1.userid=25 AND tb2.userid=25 ...

中不存在匹配的行,也要更新mytable1
mytable2

如果 UPDATE mytable1 tb1 LEFT JOIN mytable2 tb2 ON tb2.userid=25 SET tb1.save='' , tb2.save='' WHERE tb1.userid=25 中的行没有userid = 25,那么这将不会更新任何行。

MySQL不支持mytable1。但你尝试这样的事情,使用内联视图返回一行,然后对mytable1和mytable2执行外连接......

FULL OUTER JOIN

SQLFiddle演示:http://sqlfiddle.com/#!9/6f8598/1

<强>后续

“join”是一种常见的SQL操作。你不应该在找到有关它的功能的信息方面遇到任何麻烦。

“+ 0”并非绝对必要。这是MySQL中CAST到数字的便捷简写。作为测试,看看MySQL为此返回的内容:

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

内联视图的目的是返回单行。我们可以编写查询来对user_id进行两次硬编码,并忽略从行视图返回的内容....

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

我的偏好是更清楚地表明我们的意图是使两个值相同。我们可以编写其中一个是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 = 25
   LEFT
   JOIN mytable t2
     ON t2.user_id = 25

我们有点“失去”这两个价值相同的想法。为了获得仅指定一次的硬编码值,我让内联视图返回我们想要在外连接的ON子句中“匹配”的值。

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

现在我的意图更清楚......我正在寻找“一个”user_id值。添加“+ 0”表示无论传入什么值(例如'25','foo'或其他什么),我的声明都会将其解释为数值。

内联视图

我使用了“内联视图”这个术语。这只是我们通常有一个表的上下文中使用的SELECT查询。

e.g。如果我有一个名为 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 的表,我可以写一个查询...

mine

测试它并看到它返回行,yada,yada。

我也可以这样做:在parens中包装该查询并在另一个语句中引用它到位,就像这样......

  SELECT m.id, m.name FROM mine m

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

(这只是模式的一个示例;我们不想这样做的原因。)

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

然后我们可以这样做:

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

使用内嵌视图,我们遵循相同的模式,但我们绕过了单独的 SELECT t.* FROM myview t 语句。 (这是一个导致隐式提交和创建数据库对象的DDL语句。)绕过它,我们有效地创建了一个仅存在于语句上下文中的视图,并在语句中执行“内联”。 / p>

create view

MySQL文档将内联视图称为“派生表”。如果我们(意外地)忘记别名,我们得到的错误就说“每个派生表必须有一个别名”。用于除MySQL以外的数据库的更通用的术语是“内联视图”。