跨3个表的SQL Update - Where子句问题(?)

时间:2016-03-31 15:10:54

标签: php sql join where clause

我们需要通过输入表单更新3个不同表上的各个列。其中大部分都是有用的,但是当我们尝试更新已加入的其他2个表(发布者和类别)时,它会使用相同的输入更新该记录和每个其他记录。

(例如,如果我们将音乐类型从金属改为爵士音乐,那么所有金属CD也将改为爵士音乐)

以下是我们到目前为止的更新代码。

$sql = "UPDATE nmc_cd, nmc_category, nmc_publisher 
SET CDTitle ='$title', CDYear = '$year', nmc_publisher.pubID = '$publisherID', nmc_category.catID = '$categoryID', CDPrice = '$price', pubName ='$pubName', catDesc='$catDesc'
WHERE CDID = $id
AND nmc_category.catID = nmc_cd.catID
AND nmc_publisher.pubID = nmc_cd.pubID";

我对这个网站比较新,所以如果需要代码,变量/功能等名称,请说出来,我会编辑我的帖子或回复。

提前致谢!

1 个答案:

答案 0 :(得分:0)

一些建议。

1)在SQL语句中限定所有列引用,引用多个表,即使列引用与MySQL不明确。 (还要考虑为每个表分配一个简短的别名。)有几个原因,但一个重要原因是它让人类读者知道每个引用列所在的表。

2)抛弃旧学校逗号运算符以进行联接操作,并使用JOIN关键字。同时将连接谓词从WHERE子句移动到相应的ON子句。

3)对于多表更新,首先编写SELECT语句,使其正常工作并进行测试,然后将其转换为UPDATE语句

4)避免SQL注入漏洞。首选模式是使用带有绑定占位符的预准备语句。或者(不太理想)至少,必须正确转义SQL文本中包含的所有可能不安全的值。

忽略SQL注入漏洞(假设变量的内容已经被正确转义)...

我首先编写一个SELECT语句,它返回我们计划更新的列的当前值,以及我们计划分配给这些列的新值。例如:

 SELECT cd.cdtitle      AS old_cd_cdtitle
      , '$title'        AS new_cd_cdtitle

      , cd.cdyear       AS old_cdyear
      , '$year'         AS new_cdyear

      , pub.pubid       AS old_pub_pubid
      , '$publisherID'  AS new_pub_pubid

      , cat.catid       AS old_cat_catid
      , '$categoryID'   AS new_cat_catid

      , cd.cdprice      AS old_cd_cdprice
      , '$price'        AS new_cd_cdprice

      , pub.pubName     AS old_pub_pubname
      , '$pubName'      AS new_pub_pubname

      , cat.catDesc     AS old_cat_catdesc
      , '$catDesc'      AS new_cat_catdesc

   FROM nmc_cd cd
   JOIN nmc_category cat
     ON cat.catID = cd.catid
   JOIN nmc_publisher pub
     ON pub.pubID = cd.pubid
  WHERE cd.cdid = $id

(这只是猜测,我不确定你实际上想要实现的目标。)

在连接谓词中引用新值时,为catid列分配新值似乎很奇怪。要维护cdcat中的行之间的关系,需要更新两个表中的catid列,除非我们依赖于ON UPDATE CASCADE规则传播变化。

如果不了解此声明试图实现的内容,则无法推荐任何特定声明。

在将SELECT转换为UPDATE语句方面,请将SELECT ... FROM替换为关键字UPDATE

WHERE子句之前,添加SET语句。从SELECT列表中获取old_cd_cdyear和new_cd_cdyear的表达式,将其转换为如下的SET子句:

    SET cd.cdyear       = '$year'

后续分配,使用逗号代替SET关键字,例如

      , cd.cdprice      = '$price'