我正在尝试运行查询,以便在重复时插入或更新。我正在使用复制的唯一索引,但我似乎无法让它工作。它仍然增加了新的记录。希望一些新鲜的眼睛可以指出我的问题。感谢。
这是我的架构
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值进行测试,但仍然没有...这是我的架构还是我的查询仍然存在问题?
答案 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,索引需要持久性。