【问题标题】:Bug in sqlfiddle OR I don't understand INSERT ... ON DUPLICATE KEY UPDATEsqlfiddle 中的错误或者我不明白 INSERT ... ON DUPLICATE KEY UPDATE
【发布时间】:2012-05-15 18:02:21
【问题描述】:

这个 sqlfiddle 链接似乎在调用之间保持状态: http://sqlfiddle.com/#!2/125bc/1

它包含 mysql 的这个模式:

CREATE TABLE if not exists  `standings` (
  `teamid` int(11) NOT NULL,
  `win` decimal(23,0) default NULL,
  `tie` decimal(23,0) default NULL,
  `lose` decimal(23,0) default NULL,
  PRIMARY KEY  (`teamid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


INSERT INTO `standings` (`teamid`, `win`, `tie`, `lose`) VALUES
(1, 3, 0, 0),
(2, 1, 1, 1),
(3, 1, 1, 1),
(4, 0, 0, 3);


CREATE TABLE if not exists `newscores` (
  `recordid` int(11) NOT NULL auto_increment,
  `teamid` int(11) NOT NULL,
  `gameid` int(11) NOT NULL,
  `totalstrokes` int(11) NOT NULL,
  primary key (recordid)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;



INSERT INTO `newscores` (`recordid`, `teamid`, `gameid`, `totalstrokes`) VALUES
(5, 1, 1, 145),
(6, 2, 1, 105),
(7, 5, 1, 145),
(8, 6, 1, 155);

还有这两个查询:

Insert into  standings (teamid, win, tie, lose) (SELECT g1.teamid, SUM( IF( g1.totalstrokes < g2.totalstrokes, 1, 0 ) ) AS win, SUM( IF( g1.totalstrokes = g2.totalstrokes, 1, 0 ) ) AS tie, SUM( IF( g1.totalstrokes > g2.totalstrokes, 1, 0 ) ) AS lose
FROM newscores g1
JOIN newscores g2 ON g1.gameid = g2.gameid
AND g1.teamid != g2.teamid
GROUP BY g1.teamid) 
on duplicate key 
update win = win + values(win), 
lose = lose + values(lose), 
tie = tie + values(tie);

select * from standings;

它应该产生这个standings 表:

teamid   win tie lose
  1       4   1   1
  2       4   1   1
  3       1   1   1
  4       0   0   3
  5       1   1   1
  6       0   0   3

第一次运行时确实如此。第二次运行时(通过将 url 粘贴到新窗口中),teamids 1,2,5,6 的一些值会增加。

我可以通过编辑架构来重置它,将“创建表”更改为“如果不存在表则创建”,反之亦然,或者包括“删除表”语句。但这似乎很奇怪。

PS 如果有人比我更有意义,我会为这个问题添加一个 sqlfiddle 标签。

【问题讨论】:

    标签: mysql sql sqlfiddle


    【解决方案1】:

    我是 SQL Fiddle 的作者。这种行为有一个非常简单的解释。本质上,您在右侧面板(“运行查询”侧)上运行的所有查询都在事务块中执行,该事务块立即回滚以保留模式的状态(由左侧定义控制板)。大多数情况下,所有内容都会返回到事情开始的确切位置,因为在事务中执行的大多数内容都可以回滚。然而,正如我在早期使用 SQL Fiddle 时发现的,少数不会回滚的事情之一是自动递增 ID 值。这是所有供应商有意做出的设计决定,旨在确保您的主键不会因重用而发生冲突。

    由于自动 id 应该是没有意义的,所以对于 SQL Fiddle 来说,这件事的改变从来没有真正让我印象深刻(特别是因为大多数人无论如何都在左侧运行他们的插入)。

    您无需打开多个窗口即可看到此行为,顺便说一句 - 只需多次点击“运行查询”,您就会看到它发生了变化。您还可以使用我的 SQL Server 示例小提琴来查看它:http://sqlfiddle.com/#!3/1fa93/1 只需多次运行该查询,您就会看到 id 每次都发生变化。 (如果有一段时间没有使用小提琴,它将重置,因为在特定小提琴未使用后,我删除了正在运行的数据库以释放内存)。

    编辑

    哇!抱歉,没有足够仔细地阅读您的查询。我现在明白发生了什么。您正在使用 MyISAM 表而不是 InnoDB。我真的需要禁用这些作为 MySQL 的选项。你看,他们根本不支持交易。因此,当我尝试回滚对这些表的更新时,更新根本不会回滚。你不断地增加它们。当我第一次推出 MySQL 作为一个选项时,我看到了这一点,因为默认情况下 MySQL 使用 MyISAM。我必须将默认值更改为 InnoDB 才能使事务正常工作。

    在这里,当我简单地删除您对 MyISAM 的显式使用时,您可以看到它运行良好:http://sqlfiddle.com/#!2/cec6e/1

    更新

    由于对 MySQL 的一些更改要求,这里是我稍微重新安排的版本:http://sqlfiddle.com/#!2/a9cc3/1

    【讨论】:

    • 您创建了一个很棒的工具(我已经广泛使用)。恭喜:)
    • 感谢@MostyMostacho 我已经看到您使用该网站的工作,非常令人印象深刻的东西。你总是得到我的支持!
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 2018-06-27
    • 2013-10-03
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    相关资源
    最近更新 更多