Mysql UPDATE ON DUPLICATE KEY只插入

时间:2014-07-27 06:38:04

标签: mysql upsert

我正在尝试运行查询,以便在重复时插入或更新。我正在使用复制的唯一索引,但我似乎无法让它工作。它仍然增加了新的记录。希望一些新鲜的眼睛可以指出我的问题。感谢。

这是我的架构

CREATE TABLE IF NOT EXISTS `pricing_puchasing` (
  `custno` varchar(6) DEFAULT NULL COMMENT 'customer code',
  `recipe` varchar(15) DEFAULT NULL,
  `item` varchar(120) NOT NULL COMMENT 'Item Code from dProduce',
  `unit_weight` double(12,4) DEFAULT NULL,
  `case_cost` double(12,4) DEFAULT NULL COMMENT 'Projected cost of item',
  `cost_per_lb` double(12,4) NOT NULL,
  `projected_price` float(12,3) DEFAULT NULL COMMENT 'projected Price',
  `projected_margin` float(12,3) DEFAULT NULL COMMENT 'Projected Margin',
  `trend` tinyint(1) DEFAULT NULL COMMENT 'Trend status 1=up, 0=down',
  `note` varchar(255) DEFAULT NULL COMMENT 'Note about the data',
  `week_of` date NOT NULL COMMENT 'Week of this data',
  `approved` tinyint(1) DEFAULT NULL COMMENT 'approval flag',
  `last_edited_from` varchar(20) NOT NULL COMMENT 'identifier to know where it was last saved from',
  `saved_at` datetime NOT NULL COMMENT 'Date time of save/update',
  `saved_by` int(11) NOT NULL COMMENT 'Created by user ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Stores pricing purchasing data';


ALTER TABLE `pricing_puchasing`
 ADD UNIQUE KEY `custno_recipe_item_week_of` (`custno`,`recipe`,`item`,`week_of`), ADD KEY `custno` (`custno`);

这是我正在测试的查询:

INSERT INTO pricing_puchasing 
    (recipe,item,unit_weight,case_cost,cost_per_lb,trend,note,week_of,saved_at,saved_by,approved,last_edited_from) 
VALUES 
    ('APPLEGRRAW','APPLEGRRAW',40.00,100.01,2.50,0,'','2014-07-28',NOW(),1,NULL,'purchasing') 
ON DUPLICATE KEY UPDATE 
    unit_weight=40.00,case_cost=100.01,cost_per_lb=2.50,trend=0,note='',saved_at=NOW(),saved_by=1,approved=NULL,last_edited_from='purchasing'

修改 我修复了custno丢失的问题,但我仍然遇到插入重复的问题。我创建了一个sqlfiddle。这次我正在使用2个NULL值进行测试,但仍然没有...这是我的架构还是我的查询仍然存在问题?

4 个答案:

答案 0 :(得分:3)

NULL值不被视为"唯一"。唯一索引中的第一列是custno,您不能在INSERT中为该列提供值,因此默认值NULL用作该列的值。

由于NULL值不被认为是唯一的,因此INSERT不会抛出重复的键异常。

尝试使用custno列的非NULL值。


此外,您可以在语句的UPDATE部分中使用特殊的VALUES()函数来引用INSERT中提供的值。

ON DUPLICATE KEY UPDATE 
    unit_weight=VALUES(unit_weight),case_cost=VALUES(case_cost)

http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_values

答案 1 :(得分:2)

UNIQUE约束不会将NULL计为重复项。也就是说,您可以将多行与NULL作为唯一键的一列或多列。

您的INSERT语句未指定custno的值,正如@Fabricator在评论中指出的那样。 custno列的默认值为NULL,因此INSERT不会违反唯一约束。

答案 2 :(得分:0)

问题是您的表没有主键,而您的查询也没有指定密钥。假设custno是主键,您可以在insert语句中使用mysql replace statement而不是更新重复键。在这种情况下,它将是

REPLACE INTO pricing_puchasing 
(custno,recipe,item,unit_weight,case_cost,cost_per_lb,trend,note,week_of,saved_at,saved_by,approved,last_edited_from)
VALUES 
('123','bbfAPPLEGRRAW','APPLEGRRAW',40.00,100.01,2.50,0,'','2014-07-28',NOW(),1,NULL,'purchasing');

答案 3 :(得分:0)

如前所述(spencer7593等),null!= null,因此可空字段在唯一键中不能很好地工作。但是,如果添加MySQL生成的存储列或MariaDB持久虚拟列以间接地对可空字段应用唯一性约束,则可以使用插入重复键更新语句简单地完成upsert。

e.g。

CREATE TABLE IF NOT EXISTS `pricing_puchasing` (
  `custno` varchar(6) DEFAULT NULL COMMENT 'customer code',
  `vcustno` varchar(6) AS (COALESCE(custno, '')) STORED,
  `recipe` varchar(15) DEFAULT NULL,
  `vrecipe` varchar(15) AS (COALESCE(recipe, '')) STORED,
  `item` varchar(120) NOT NULL COMMENT 'Item Code from dProduce',
  `unit_weight` double(12,4) DEFAULT NULL,
  `case_cost` double(12,4) DEFAULT NULL COMMENT 'Projected cost of item',
  `cost_per_lb` double(12,4) NOT NULL,
  `projected_price` float(12,3) DEFAULT NULL COMMENT 'projected Price',
  `projected_margin` float(12,3) DEFAULT NULL COMMENT 'Projected Margin',
  `trend` tinyint(1) DEFAULT NULL COMMENT 'Trend status 1=up, 0=down',
  `note` varchar(255) DEFAULT NULL COMMENT 'Note about the data',
  `week_of` date NOT NULL COMMENT 'Week of this data',
  `approved` tinyint(1) DEFAULT NULL COMMENT 'approval flag',
  `last_edited_from` varchar(20) NOT NULL COMMENT 'identifier to know where it was last saved from',
  `saved_at` datetime NOT NULL COMMENT 'Date time of save/update',
  `saved_by` int(11) NOT NULL COMMENT 'Created by user ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Stores pricing purchasing data';

ALTER TABLE `pricing_puchasing`
 ADD UNIQUE KEY `custno_recipe_item_week_of` (`vcustno`,`vrecipe`,`item`,`week_of`), ADD KEY `custno` (`custno`);

对于MariaDB,用PERSISTENT替换STORED,索引需要持久性。

MySQL Generated Columns MariaDB Virtual Columns