sqlfiddle中的错误或者我不明白INSERT ... ON DUPLICATE KEY UPDATE

Cit*_*ols 2 mysql sql sqlfiddle

这个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);
Run Code Online (Sandbox Code Playgroud)

这两个问题:

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;
Run Code Online (Sandbox Code Playgroud)

它应该导致这个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
Run Code Online (Sandbox Code Playgroud)

它确实是第一次运行.第二次运行(通过将URL粘贴到新窗口中),teamids 1,2,5,6的一些值会递增.

我可以通过编辑模式来重置它,将"create table"更改为"create if not exists table",反之亦然,或者包括"drop table"语句.但这似乎很奇怪.

PS如果有人比我在这个问题上添加了一个sqlfiddle标签更有意义,我将不胜感激.

Jak*_*sel 15

我是SQL Fiddle的作者.这种行为有一个非常简单的解释.实质上,您在右侧面板("运行查询"侧)上运行的所有查询都在事务块中执行,该事务块立即回滚以保留架构的状态(由左侧定义)面板).大多数情况下,所有内容都会返回到事物开始的位置,因为事务中执行的大多数内容都可以回滚.但是,正如我在SQL Fiddle早期发现的那样,无法回滚的少数事情之一是自动递增ID值.这是所有供应商的有意设计决策,它旨在确保您的主键永远不会与重用相冲突.

由于自动ID应该没有意义,因此对于SQL Fiddle来说,这一件事情的变化从来没有让我感到震惊(特别是因为大多数人都在左侧运行他们的插件).

您可以在不打开多个窗口的情况下看到此行为,顺便说一下 - 只需多次点击"运行查询",您就会看到它发生变化.您还可以使用我的SQL Server示例小提琴来查看它:http://sqlfiddle.com/#!3/ 1fa93/1 只需多次运行该查询,您就会看到每次更改ID.(如果在一段时间内没有使用小提琴,它将重置,因为我放弃正在运行的DB以在特定小提琴未使用后释放内存).

编辑

卫生署!对不起,没有仔细阅读你的查询.我现在看到发生了什么.您正在使用MyISAM表而不是InnoDB.我真的需要禁用那些作为MySQL的选项.你看,他们根本不支持交易.因此,当我尝试回滚对这些表的更新时,更新根本就不会回滚.你继续递增它们.当我第一次推出MySQL作为选项时,我看到了这一点,因为默认情况下MySQL使用MyISAM.我不得不将默认值更改为InnoDB以使事务正常工作.

我只是删除你对MyISAM的明确使用,你可以看到它正常工作:http://sqlfiddle.com/#!2/cec6e/1

更新

由于MySQL的一些变化要求,我在这里稍微重新安排了这个版本:http://sqlfiddle.com/#!2/a9cc3/1

  • 你已经创建了一个很棒的工具(我已经广泛使用了它).恭喜:) (9认同)