我寫了一個存儲過程來更新並將記錄插入MariaDB版本15.1,distrib 10.0.13-MariaDB for Win64(x86)。MariaDB存儲過程在更新時重複條目?
我的存儲過程:
exitProc:BEGIN
#--
# procCreateUser
# Parameters:
# biPerson_id, the id of the user, NULL if new
# vcFirstName, the christian name of the user
# vcMiddleName, optional, middle name of the user
# vcSurName, the surname of the user
# vcEmail, the email associated with the user
# biDept, the department ID
# biRole, the role ID
# vcUsername, the login name of the user
# vcPassword, the password for the user
# vcIPorHost, the IP address or Host name of the client
# biUID, the user ID of the user performing this procedure
#--
DECLARE txtAuditEntry TEXT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
CALL procLogError(CONCAT("procCreateUser: "
,@errno, " (", @sqlstate, "): ", @text));
END;
#Prepare the parameters
IF (vcFirstName IS NULL) OR (LENGTH(TRIM(vcFirstName)) = 0) THEN
CALL procLogError("vcFirstName must be valid");
LEAVE exitProc;
ELSEIF (vcSurName IS NULL) OR (LENGTH(TRIM(vcSurName)) = 0) THEN
CALL procLogError("vcSurName must be valid");
LEAVE exitProc;
ELSEIF (vcEmail IS NULL) OR (LENGTH(TRIM(vcEmail)) = 0) THEN
CALL procLogError("vcEmail must be valid");
LEAVE exitProc;
ELSEIF (biDept_id IS NULL) OR (biDept_id = 0) THEN
CALL procLogError("biDept_id must be valid");
LEAVE exitProc;
ELSEIF (biRole_id IS NULL) OR (biRole_id = 0) THEN
CALL procLogError("biRole_id must be valid");
LEAVE exitProc;
ELSEIF (vcUsername IS NULL) OR (LENGTH(TRIM(vcUsername)) = 0) THEN
CALL procLogError("vcUsername must be valid");
LEAVE exitProc;
END IF;
#Report parameters
CALL procAuditEntry(CONCAT("biPerson_id: ", biPerson_id), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("vcFirstName: ", vcFirstName), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("vcMiddleName: ", vcMiddleName), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("vcSurName: ", vcSurName), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("vcEmail: ", vcEmail), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("biDept_id: ", biDept_id), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("biRole_id: ", biRole_id), vcIPorHost, biCreator_id);
CALL procAuditEntry(CONCAT("vcUsername: ", vcUsername), vcIPorHost, biCreator_id);
IF (biPerson_id IS NULL) THEN
CALL procAuditEntry("INSERT", vcIPorHost, biCreator_id);
INSERT INTO `tbl_people` (
`vcFirstName`
,`vcMiddleName`
,`vcSurName`
,`vcEmail`
,`biDept_id`
,`biRole_id`
,`vcUserName`
,`vcPassWord`
) VALUES (
vcFirstName
,vcMiddleName
,vcSurName
,vcEmail
,biDept_id
,biRole_id
,vcUsername
,vcPassword
);
#Create audit log entry
SET txtAuditEntry = CONCAT('user \'', vcUsername, '\' created');
CALL procAuditEntry(txtAuditEntry, vcIPorHost, biCreator_id);
ELSE
CALL procAuditEntry("A.UPDATE", vcIPorHost, biCreator_id);
UPDATE `tbl_people` SET
`vcFirstName`=vcFirstName
,`vcMiddleName`=vcMiddleName
,`vcSurName`=vcSurName
,`vcEmail`=vcEmail
,`biDept_id`=biDept_id
,`biRole_id`=biRole_id
,`vcUserName`=vcUsername
WHERE
`biPerson_id`=biPerson_id;
CALL procAuditEntry("B.UPDATE", vcIPorHost, biCreator_id);
IF NOT vcPassWord IS NULL THEN
UPDATE `tbl_people` SET
`vcPassWord`=vcPassword
WHERE
`biPerson_id`=biPerson_id;
END IF;
#Create audit log entry
SET txtAuditEntry = CONCAT('user \'', vcUsername, '\' updated');
CALL procAuditEntry(txtAuditEntry, vcIPorHost, biCreator_id);
END IF;
END
所有來電「procAuditEntry」實際上只是用於調試,當我把這個過程創建一個新的紀錄我傳遞的第一個參數爲空。
我可以從審計表中看到它將進入過程的UPDATE部分。問題是,我得到了程序引發的重複鍵錯誤,我不理解,因爲沒有創建新條目,只有正在修改的現有條目。該表的定義如下:
CREATE TABLE `tbl_people` (
`biPerson_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
`biCompany_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL COMMENT 'Link to companies table',
`biDept_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL COMMENT 'Link to department table',
`biRole_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL COMMENT 'Link to Job title/description',
`tiActive` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '1=active, 0=not',
`dtLastLogin` DATETIME NULL DEFAULT NULL COMMENT 'Date/Time of last login',
`vcFirstName` VARCHAR(48) NOT NULL COMMENT 'First name',
`vcMiddleName` VARCHAR(48) NULL DEFAULT NULL COMMENT 'Middle name',
`vcSurName` VARCHAR(48) NOT NULL COMMENT 'Surname',
`vcEmail` VARCHAR(256) NOT NULL COMMENT 'Email address',
`vcUserName` VARCHAR(48) NOT NULL COMMENT 'User name',
`vcPassWord` VARCHAR(32) NOT NULL COMMENT 'Password',
PRIMARY KEY (`biPerson_id`),
UNIQUE INDEX `Name` (`vcFirstName`, `vcSurName`),
UNIQUE INDEX `userName` (`vcUserName`),
INDEX `active` (`tiActive`),
INDEX `dept` (`biDept_id`),
INDEX `company` (`biCompany_id`),
INDEX `lastLogin` (`dtLastLogin`),
INDEX `jobrole` (`biRole_id`)
)
COMMENT='All timekeeper users'
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4;
正在記錄的錯誤是:
procCreateUser:1062(23000):重複的項目 '西蒙 - Platten' 關鍵 '名稱'
的非常奇怪事情是,如果我在存儲過程的外面調用它的UPDATE它工作。
用REPLACE語句替換UPDATE解決了這個問題,只是不確定UPDATE失敗的原因。
避免命名變量和參數等於你的表的列名。 – wchiquito
「UNIQUE INDEX'Name'('vcFirstName','vcSurName'),」在這之前會有多久真的有一個同名的第二個人? –
考慮通過使用'INSERT ... ON DUPLICATE KEY UPDATE ...'來縮短代碼。 –