MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引
Posted
技术标签:
【中文标题】MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引【英文标题】:MySQL handle duplicate key error insert into table with multiple unique indexes; not multi-column unique index 【发布时间】:2013-03-19 17:19:02 【问题描述】:如何从存储过程中找到哪个唯一索引失败?
我创建了一个单列主键和三个单列唯一索引的表:
CREATE TABLE tableName (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
col1 VARCHAR(50) NOT NULL,
col2 VARCHAR(50) NOT NULL,
col3 VARCHAR(50) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX id_UNIQUE (id ASC),
UNIQUE INDEX col1_UNIQUE (col1 ASC),
UNIQUE INDEX col2_UNIQUE (col2 ASC),
UNIQUE INDEX col3_UNIQUE (col3 ASC)
) ENGINE = InnoDB;
我创建了一个存储过程来处理错误'1062':'Duplicate entry %s for key %d':
DELIMITER $$
CREATE PROCEDURE insertRecord (
col1Value VARCHAR(50),
col2Value VARCHAR(50),
col3Value VARCHAR(50),
OUT idValue INT,
OUT errColName VARCHAR(50)
) BEGIN
DECLARE EXIT HANDLER FOR 1062 BEGIN
SET errColName = 'Insert Column Name Here';
END;
INSERT tableName SET
col1 = col1Value,
col2 = col2Value,
col3 = col3Value;
SET idValue = LAST_INSERT_ID();
END;
$$
DELIMITER ;
我已经用不同的数据调用了存储过程 5 次以返回各种结果:
第一次插入尝试成功
-- Initialize parameters
SET @col1Val = 'mysql',
@col2Val = 'Is',
@col3Val = 'Cool',
@Id = NULL,
@ErrColName = NULL;
-- 1st Insert Attempt
CALL insertRecord(@col1Val, @col2Val, @col3Val, @Id, @ErrColName);
-- Expected result: @Id = 1, @ErrColName = NULL
SELECT @Id '@Id', @ErrColName '@ErrColName';
第二次插入尝试失败,因为 col1 不是唯一的
-- Re-initialize parameters
SET @col1Val = 'MySQL', -- Intended to generate an error
@col2Val = 'Is',
@col3Val = 'Cool',
@Id = NULL,
@ErrColName = NULL;
-- 2nd Insert Attempt
CALL insertRecord(@col1Val, @col2Val, @col3Val, @Id, @ErrColName);
-- Expected result: @Id = NULL, @ErrColName = 'col1'
SELECT @Id '@Id', @ErrColName '@ErrColName';
第三次插入尝试失败,因为 col2 不是唯一的
-- Re-initialize parameters
SET @col1Val = 'SQL',
@col2Val = 'Is', -- Intended to generate an error
@col3Val = 'Cool',
@Id = NULL,
@ErrColName = NULL;
-- 3rd Insert Attempt
CALL insertRecord(@col1Val, @col2Val, @col3Val, @Id, @ErrColName);
-- Expected result: @Id = NULL, @ErrColName = 'col2'
SELECT @Id '@Id', @ErrColName '@ErrColName';
第四次插入尝试失败,因为 col3 不是唯一的
-- Re-initialize parameters
SET @col1Val = 'SQL',
@col2Val = 'For',
@col3Val = 'Cool', -- Intended to generate an error
@Id = NULL,
@ErrColName = NULL;
-- 4th Insert Attempt
CALL insertRecord(@col1Val, @col2Val, @col3Val, @Id, @ErrColName);
-- Expected result: @Id = NULL, @ErrColName = 'col3'
SELECT @Id '@Id', @ErrColName '@ErrColName';
第 5 次插入尝试成功
-- Re-initialize parameters
SET @col1Val = 'SQL',
@col2Val = 'For',
@col3Val = 'Life',
@Id = NULL,
@ErrColName = NULL;
-- 5th Insert Attempt
CALL insertRecord(@col1Val, @col2Val, @col3Val, @Id, @ErrColName);
-- Expected result: @Id = 5, @ErrColName = NULL
SELECT @Id '@Id', @ErrColName '@ErrColName';
我需要在存储过程中做什么才能从存储过程中找出哪个唯一索引失败了?
提前致谢。
【问题讨论】:
【参考方案1】:我在Which unique key is hit with my insert? 下找到了答案。这并不理想,但确实解决了问题。
以下是应用的解决方案:
...
DECLARE EXIT HANDLER FOR 1062 BEGIN
-- Check if col1Value is already in use
IF EXISTS (
SELECT 1
FROM tableName
WHERE col1 = col1value
LIMIT 1
) THEN
SET errColName = 'Col1';
-- Check if col2Value is already in use
ELSEIF EXISTS (
SELECT 1
FROM tableName
WHERE col2 = col2value
LIMIT 1
) THEN
SET errColName = 'Col2';
-- Check if col3Value is already in use
ELSEIF EXISTS (
SELECT 1
FROM tableName
WHERE col3 = col3value
LIMIT 1
) THEN
SET errColName = 'Col3';
END IF;
END;
...
【讨论】:
以上是关于MySQL处理重复键错误插入具有多个唯一索引的表;不是多列唯一索引的主要内容,如果未能解决你的问题,请参考以下文章
oracle 数据库 - 插入具有唯一键约束的表显示当值实际重复时插入 1 行。 - 发生在函数中