【问题标题】:MySQL UPDATE or INSERT depending on the existance of an IDMySQL UPDATE 或 INSERT 取决于 ID 的存在
【发布时间】:2023-03-05 10:05:01
【问题描述】:

我正在跟踪许多类似网站上的访问者移动,并已分配目标以跟踪每个目标的不同值。由于这些目标是动态创建的,因此我还需要动态更新它们。 mysql 结构的相关部分如下,它在 2 个站点上描述了相同的 4 个目标。 注意:每个站点的目标始终相同。

CREATE TABLE IF NOT EXISTS `goals` (
  `idsite` int(11) NOT NULL,
  `idgoal` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  `allow_multiple` tinyint(4) NOT NULL,
  `revenue` float NOT NULL,
  PRIMARY KEY (`idsite`,`idgoal`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `goals` (`idsite`, `idgoal`, `name`, `allow_multiple`, `revenue`) VALUES
(10, 1, 'Product Benefits Video',   0,  2),
(10, 2, 'Agent Benefits Video',     0,  4),
(10, 3, 'Social Network Video',     0,  6),
(10, 4, 'MMP Overview Video',       1,  8),
(13, 1, 'Product Benefits Video',   0,  2),
(13, 2, 'Agent Benefits Video',     0,  4),
(13, 3, 'Social Network Video',     0,  6),
(13, 4, 'MMP Overview Video',       1,  8);

上面的插入命令是从一个数组中创建的,如下所示。

$config['trackings'][1] = array('name'=>'Product Benefits Video',   'value'=>'2',   'multi'=>'0');
$config['trackings'][2] = array('name'=>'Agent Benefits Video', 'value'=>'3',   'multi'=>'0');
$config['trackings'][3] = array('name'=>'Social Network Video', 'value'=>'4',   'multi'=>'0');
$config['trackings'][4] = array('name'=>'MMP Overview Video',       'value'=>'5',   'multi'=>'1');

我永远不需要删除目标,但我想知道如何更改值,如果目标不存在,请将其添加到所有网站。

如果我提供一个新数组的示例如下:

$config['trackings'][1] = array('name'=>'Product Benefits Video',   'value'=>'6',   'multi'=>'0');
$config['trackings'][2] = array('name'=>'Agent Benefits Video', 'value'=>'7',   'multi'=>'0');
$config['trackings'][3] = array('name'=>'Social Network Video', 'value'=>'8',   'multi'=>'1');
$config['trackings'][4] = array('name'=>'MMP Overview Video',       'value'=>'9',   'multi'=>'1');
$config['trackings'][5] = array('name'=>'MMP Details Video',        'value'=>'10',  'multi'=>'1');

我想添加目标 5 并更新每个站点的现有目标的值和 allow_multiple。

我考虑过截断表格并从头开始重写所有值,但有成千上万的网站。 我也玩过替换、插入更新并最终拔掉了我的头发。

有没有比清空批次更简单的方法?

编辑: 最终结果应该是这样的

(10, 1, 'Product Benefits Video',   0,  6),
(10, 2, 'Agent Benefits Video',     0,  7),
(10, 3, 'Social Network Video',     1,  8),
(10, 4, 'MMP Overview Video',       1,  9),
(10, 5, 'MMP Details Video',        1,  10),
(13, 1, 'Product Benefits Video',   0,  6),
(13, 2, 'Agent Benefits Video',     0,  7),
(13, 3, 'Social Network Video',     1,  8),
(13, 4, 'MMP Overview Video',       1,  9);
(13, 5, 'MMP Details Video',        1,  10);

编辑:这将很容易完成所有更新

foreach($config['trackings'] as $id => $track)
{
    $s = "UPDATE `goals` SET `revenue` = ".$track['value'].", `allow_multiple` = ".$track['multi']." WHERE `idgoal` = '".$id."'";
}

但是如何同时添加缺失的目标(5)?

【问题讨论】:

    标签: php mysql arrays multidimensional-array mysqli


    【解决方案1】:

    您有所有网站的表格吗?如果是,您可以像这样使用REPLACE

    REPLACE INTO goals (idsite, idgoal, name, allow_multiple, revenue)
    SELECT idsite, 5, 'MMP Details Video', 1, 10 FROM sites;
    

    这里sites 是所有具有列idsite 的站点的表,其含义与表goals 中的列idsite 相同。

    该语句将新记录插入到sites 表中定义的每个站点的goals 表中,其值为idside, 5, 'MMP Details Video', 1, 10,其中idsite 是取自sites 表的idsite 列的值。如果idsiteidgoal相同的记录已经存在,则替换为新记录。

    【讨论】:

    • 出色,经过测试,工作起来就像一个魅力!我从来不知道我可以使用字符串作为这样的选择。非常感谢!
    • @AndyGee 不客气!
    【解决方案2】:

    好的,我想通了,我把它分成了两部分。

    $s = "SELECT MAX(`idgoal`) AS slice FROM goals";    //4
    $slice = 4;
    $track_update = array_slice($config['trackings'], 0, $slice, true);
    
    foreach($track_update as $id => $track){ //4 queries
        $s = "UPDATE `goals` SET `revenue` = ".$track['value'].",
                `allow_multiple` = ".$track['multi']." WHERE `idgoal` = '".$id."'";
    }
    
    //now to add new values
    $s = "SELECT DISTINCT(`idsite`) AS mid FROM goals";     //array(10,13)
    $result = array(10,13);
    
    $track_add = array_slice($config['trackings'], $slice, count($config['trackings']), true);
    
    foreach($track_add as $id => $track){  //1 query for each site
        foreach($result as $idsite){
            $sx[] = "(
                            ".$idsite.", ".$id.",
                            '".$track['name']."',
                            ".$track['multi'].",
                            ".$track['value']."
                        )";
        }
    
        $s = "INSERT INTO `goals`
                (`idsite`, `idgoal`, `name`, `allow_multiple`, `revenue`) 
                VALUES ".implode(',',$sx);
    }
    

    总共 5 个查询:

    UPDATE `goals` SET `revenue` = 6, `allow_multiple` = 0 WHERE `idgoal` = '1'
    UPDATE `goals` SET `revenue` = 7, `allow_multiple` = 0 WHERE `idgoal` = '2'
    UPDATE `goals` SET `revenue` = 8, `allow_multiple` = 1 WHERE `idgoal` = '3'
    UPDATE `goals` SET `revenue` = 9, `allow_multiple` = 1 WHERE `idgoal` = '4'
    INSERT INTO `goals` (`idsite`, `idgoal`, `name`, `allow_multiple`, `revenue`) 
    VALUES 
    (10, 5, 'MMP Details Video', 1, 10),
    (13, 5, 'MMP Details Video', 1, 10);
    

    【讨论】:

      【解决方案3】:

      你有几个选择:

      使用INSERT IGNORE INTO table

      INSERT … ON DUPLICATE KEY UPDATE

      查看 mysql 文档以获取有关任一命令的更多信息

      【讨论】:

      • 是的,我已经尝试了一段时间,你能提供一个简单的例子吗?
      • 类似 INSERT INTO 目标(id、收入、allow_multiple、...)值($id、'blah'、'blah'、...)ON DUPLICATE KEY UPDATE
      • INSERT INTO goals (idsite, idgoal, revenue, allow_multiple) VALUES (10, 4, 44, 0) ON DUPLICATE KEY UPDATE = #1064 - 您的 SQL 语法有错误
      • 它会告诉你错误在哪里吗?完整的错误信息是什么?
      • 没关系,现在已经解决了,但是错误的其余部分说“接近 1”,这肯定是没有帮助的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 2021-12-02
      • 1970-01-01
      相关资源
      最近更新 更多