【问题标题】:MySQL - SELECT then UPDATEMySQL - 选择然后更新
【发布时间】:2014-08-26 17:38:33
【问题描述】:

我有一个用 PHP 编写的脚本,其中的这一行可以正常工作以选择我需要的数据;

$result = mysql_query("SELECT product_name, sku, qty FROM supplier_dropship_items WHERE supplier_id = '3' AND status = '2'", $db_beb);

我正在苦苦挣扎的是一种更新我选择的记录的方法,一旦选择我需要更改status = '1',以便下次我的脚本运行时它不会在选择中提取相同的数据和只会拉出表中状态为 2 的新项目。

感谢下面接受的答案的 cmets,这是我的工作结果;

$result = mysql_query("SELECT id, product_name, sku, qty FROM supplier_dropship_items WHERE supplier_id = '3' AND status = '2' FOR UPDATE", $db_beb); 

while($row = mysql_fetch_assoc($result)) 
{ 
    $sql_table_data[] = $row;
    mysql_query("UPDATE supplier_dropship_items SET status=1 WHERE id='".$row['id']."'", $db_beb); 
} 

【问题讨论】:

  • 选择查询后运行更新查询
  • 好的,对不起,我正在学习 MySQL。如果我在选择之后进行了单独更新,我可以从技术上更改可能在选择之后添加的产品,那么下次脚本运行时将无法选择该产品?如果这有意义的话。
  • 如果您只更新您首先选择的 SKU,则不会。 (或者提示您的主键是什么)
  • 您是否在表中定义了任何主键,如果有,那么您可以运行update table set status = '1' where primarykey_column in(primaykey ids of selected records)

标签: mysql select sql-update


【解决方案1】:

当您同时SELECT 时,只需执行UPDATE

改变这个:

SELECT product_name, sku, qty 
FROM supplier_dropship_items 
WHERE supplier_id = '3' AND status = '2';

到这里:

UPDATE supplier_dropship_items as t, 
(
    SELECT id, product_name, sku, qty 
    FROM supplier_dropship_items 
    WHERE supplier_id = '3' AND status = '2'
) as temp
SET status = '1' WHERE temp.ID = t.ID;

这是假设您的表中有一个 ID 列,因为这应该是它的设置方式以及任何规范化表的外观。


编辑

这是link for the documentation on this syntax

本质上,这是在尝试更新我们在此处别名为 t 的表时,同时运行一个 select 语句。
此 select 语句返回一个结果表,我们将其命名为 temp
现在想象一下,您的 select 语句的结果在 temp 内,而您要更新的整个表在 t 内。
最后,您将status 字段更新为1,其中ID(在这两个别名结果集上)匹配

【讨论】:

  • 嗨@John Ruddell,我刚刚对此进行了测试,虽然它确实更新了项目的选择,但它们没有传递给$result,以便我在我的php脚本中使用?
  • 好的,然后在运行更新之前运行查询。基本上只需运行您的查询,这样您就可以在 $result 中找到它,然后在有意义的情况下更新表格。
  • 这种语法会导致我的 MySQL 服务器出现错误: 1. 需要一个表达式。 (在位置 39 的 "(" 附近) 2. 意外的标记。(在位置 39 的 "(" 附近) 3. 找到了一条新语句,但它与前一个语句之间没有分隔符。(在位置 46 的 "SELECT" 附近)
  • @samtuke 这是有效的语法,你没有复制正确的方法吗?
  • @JohnRuddell 如上所述,您上面的解决方案不会将 product_name、sku、qty 的值返回到 $result。我认为在更新之前运行选择会破坏代码块的目的,即通过更新和选择 1 个命令来“锁定”记录,因此第二个事务无法获取/更新记录。所以我的问题是......是否可以在这个命令中将存储在 temp 中的数据推送到 $result ?
【解决方案2】:

如果supplier_dropship_items 有主键(它应该),则将这些字段包含在 SELECT 中,然后,当您循环查看结果时,执行 UPDATE 使用主键设置status,如:

UPDATE supplier_dropship_items SET status=1 WHERE <id_field>=<id_value>;

这假设您没有在并发环境中执行。如果是,则应使用 SELECT... FOR UPDATE 锁定记录以进行更新。你可以阅读它here。据我所知,这适用于 InnoDB 表上的 MySQL。

【讨论】:

  • 您也可以只锁定表,这样顺序就不会导致死锁(在 InnoDB 中)。 LOCK TABLES supplier_dropship_items WRITE
  • 感谢@Marion C'Ascanio,这非常有效,更重要的是我理解它:) 我会将结果添加到问题中以供参考。
  • 太好了,@Innov8!很高兴我能帮上忙!
猜你喜欢
  • 1970-01-01
  • 2016-06-27
  • 2014-09-01
  • 2021-01-04
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
相关资源
最近更新 更多