我已经编写了一个存储过程来更新并将记录插入MariaDB 15.1版,distrib 10.0.13-MariaDB for Win64(x86)。
我的存储过程:
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'实际上只是用于调试,当我调用此过程创建新记录时,我将第一个参数传递为null。
我可以从审计表中看到它将进入该过程的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):重复录入' Simon-Platten'关键字'姓名'
真正奇怪的是,如果我在存储过程之外调用UPDATE它就可以工作。
用REPLACE语句替换UPDATE解决了这个问题,只是不确定UPDATE失败的原因。
答案 0 :(得分:0)
虽然我使用的是更高版本的MariaDB(10.1.x),但问题也必须在10.0.x版中解决。
尝试:
> SELECT VERSION();
+---------------------------+
| VERSION() |
+---------------------------+
| 10.1.9-MariaDB-1~wily-log |
+---------------------------+
1 row in set (0.00 sec)
> DROP TABLE IF EXISTS `tbl_people`;
Query OK, 0 rows affected (0.00 sec)
> CREATE TABLE `tbl_people` (
-> `biPerson_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> `vcFirstName` VARCHAR(48) NOT NULL,
-> `vcMiddleName` VARCHAR(48) NULL DEFAULT NULL,
-> `vcSurName` VARCHAR(48) NOT NULL,
-> UNIQUE INDEX `Name` (`vcFirstName`, `vcSurName`)
-> );
Query OK, 0 rows affected (0.00 sec)
> INSERT INTO `tbl_people`
-> (`vcFirstName`, `vcMiddleName`, `vcSurName`)
-> VALUES
-> ('Simon', 'R.', 'Platten'),
-> ('Peter', 'F.', 'Lucas');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
> SELECT
-> `biPerson_id`,
-> `vcFirstName`,
-> `vcMiddleName`,
-> `vcSurName`
-> FROM
-> `tbl_people`;
+-------------+-------------+--------------+-----------+
| biPerson_id | vcFirstName | vcMiddleName | vcSurName |
+-------------+-------------+--------------+-----------+
| 1 | Simon | R. | Platten |
| 2 | Peter | F. | Lucas |
+-------------+-------------+--------------+-----------+
2 rows in set (0.00 sec)
> DELIMITER //
> DROP PROCEDURE IF EXISTS `sp_test`//
Query OK, 0 rows affected (0.00 sec)
> CREATE PROCEDURE `sp_test`(
-> biPerson_id BIGINT UNSIGNED,
-> vcFirstName VARCHAR(48),
-> vcMiddleName VARCHAR(48),
-> vcSurName VARCHAR(48)
-> )
-> BEGIN
-> UPDATE `tbl_people` SET
-> `vcFirstName` = vcFirstName,
-> `vcMiddleName` = vcMiddleName,
-> `vcSurName` = vcSurName
-> WHERE `biPerson_id` = biPerson_id;
-> END//
Query OK, 0 rows affected (0.00 sec)
> DELIMITER ;
> CALL `sp_test`(1, 'Simon', 'A.', 'Platten');
ERROR 1062 (23000): Duplicate entry 'Simon-Platten' for key 'Name'
> DELIMITER //
> DROP PROCEDURE IF EXISTS `sp_test`//
Query OK, 0 rows affected (0.00 sec)
> CREATE PROCEDURE `sp_test`(
-> `_biPerson_id` BIGINT UNSIGNED,
-> `_vcFirstName` VARCHAR(48),
-> `_vcMiddleName` VARCHAR(48),
-> `_vcSurName` VARCHAR(48)
-> )
-> BEGIN
-> UPDATE `tbl_people` SET
-> `vcFirstName` = `_vcFirstName`,
-> `vcMiddleName` = `_vcMiddleName`,
-> `vcSurName` = `_vcSurName`
-> WHERE `biPerson_id` = `_biPerson_id`;
-> END//
Query OK, 0 rows affected (0.00 sec)
> DELIMITER ;
> CALL `sp_test`(1, 'Simon', 'A.', 'Platten');
Query OK, 1 row affected (0.00 sec)
> SELECT
-> `biPerson_id`,
-> `vcFirstName`,
-> `vcMiddleName`,
-> `vcSurName`
-> FROM
-> `tbl_people`;
+-------------+-------------+--------------+-----------+
| biPerson_id | vcFirstName | vcMiddleName | vcSurName |
+-------------+-------------+--------------+-----------+
| 1 | Simon | A. | Platten |
| 2 | Peter | F. | Lucas |
+-------------+-------------+--------------+-----------+
2 rows in set (0.00 sec)