【问题标题】:update (or insert) multiple rows in one query在一个查询中更新(或插入)多行
【发布时间】:2014-06-26 11:17:29
【问题描述】:

我正在尝试在给定设置和用户 ID 数组的情况下一次更新表中的多行(或者如果它们不存在则插入它们)。

我如何从settings 表中为特定帐户的特定计算机的所有用户选择所有行的示例。这是我需要在其中插入值或更新值(如果存在)的结果集。

$stmt = $db->prepare("      
    SELECT settings.*
    FROM
        ( SELECT  account_id, computer_id
            FROM computers
            ORDER BY computer_id ASC LIMIT 0, ".$_SESSION['user']['licenses']."
        ) as c
        LEFT JOIN users
            on users.computer_id = c.computer_id
        LEFT JOIN accounts
            on accounts.account_id = c.account_id
        LEFT JOIN settings
            on settings.user_id = users.user_id
    WHERE accounts.account_id = ".$_SESSION['user']['account_id']."
");

我想要做什么: 我正在尝试更新/插入 settings 表中的三列(启用、状态和 user_id),仅用于数组中列出的那些用户 ID。 Enabled 和 status 的值对所有人都是一样的,但 user_id 会有所不同。

$users = 数组(12, 36, 43, 56, 76)

$绑定 = 数组( '启用' => 1, '状态' => 2, 'user_id' => 来自数组 );

如果我的想法是正确的,我可以根据上面列出的语句创建一个虚拟表,然后使用 ON DUPLICATE KEY UPDATE 来插入/更新该虚拟表的结果?

这可能吗?如果是这样,例如,提示或指向正确的方向?我的工作方式涉及给定数组中每个用户 id 的 foreach 循环,因此根据其计数将有 x 个查询。如果我能把它削减到只有一个,那就太好了!

更新:

好的,我现在完全糊涂了...这是对无效值的尝试...我仍然需要一种方法来为我的数组中的每个 user_id 执行此操作,如上所述。我不需要将整个 FROM 子句“保存”为新的引用吗?

$stmt = $db->prepare("
    INSERT INTO settings (user_id, enabled, status)
    VALUES (:user_id, :enabled, :alert_user)    
    SELECT user_id, enabled, status
    FROM
        ( SELECT  account_id, computer_id
            FROM computers
            ORDER BY computer_id ASC LIMIT 0, ".$_SESSION['user']['licenses']."
        ) as c
        LEFT JOIN users
            on users.computer_id = c.computer_id
        LEFT JOIN accounts
            on accounts.account_id = c.account_id
        LEFT JOIN settings
            on settings.user_id = users.user_id
        WHERE accounts.account_id = ".$_SESSION['user']['account_id']."
    ON DUPLICATE KEY UPDATE enabled = VALUES(enabled), status = VALUES(status)  
");

$binding = array(
    'enabled' => 1,
    'alert_user' => 4,
    'user_id' => 6
    );

$stmt->execute($binding);

【问题讨论】:

  • 有人吗?整晚都在研究这个,看起来越来越不可能了。我可以更新设置表中的值,但是在我执行此操作时,似乎无法将表连接到设置表中。加入其他表是必须的,因为这是确保实际更新或插入新数据的适当权限。

标签: php mysql sql sql-insert


【解决方案1】:

是的,你的想法是正确的。应该是这样的:

INSERT INTO settings (user_id, enabled, status)
SELECT user_id, enabled, status
FROM ... -- rest of your query here
ON DUPLICATE KEY UPDATE enabled = VALUES(enabled), status = VALUES(status)

ON DUPLICATE KEY UPDATE 子句中的VALUES(colname) 获取如果没有重复则将被插入的值。

好的,根据您的评论,我认为这可能是您想要的:

INSERT INTO settings (user_id, enabled, status)
SELECT :user_id, :enabled, :status
FROM ...
JOIN ...
JOIN ...
WHERE ...
ON DUPLICATE KEY UPDATE enabled = VALUES(enabled), status = VALUES(status)

如果连接返回任何行,这将插入或更新指定的行。如果没有找到任何行,则不会进行插入/更新。

如果您不希望在要连接的表中没有匹配项时返回任何内容,那么您可能应该使用内连接而不是左连接。

【讨论】:

  • 似乎无法做到这一点......我一定还是做错了什么
  • SELECT 之前去掉VALUES (:user_id, :enabled, :alert_user)。如果你需要使用这些变量来查找要插入的行,它们应该在SELECT的WHERE子句中。
  • 查看这个答案stackoverflow.com/questions/23535975/…,了解如何在 INSERT 中将参数与 SELECTed 数据混合。
  • Barmar...我根本不想找到要插入的变量...这些是我要插入settings 的值。我想做的是将表连接到settings,因此只能插入“有效”条目。例如,如果我尝试单独在 settings 上插入 user_id = 450,它会起作用。实际上,这可能不是一个有效的 user_id(用户、计算机、帐户的加入)对我的选择起作用。
猜你喜欢
  • 2017-09-12
  • 2014-02-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 2011-08-29
  • 2012-04-21
  • 2016-04-14
相关资源
最近更新 更多