0

这是我想做的事情:

称为部门的表与称为员工的表具有多对多关系。因此,表 department_employees 具有列:department_id、employee_id、is_active。

索引department_id,employee_id 为pk。

我得到一串员工 ID,例如“12,15,18,19”。我得到部门ID。

我调用了一个 Mysql 存储过程(例程),它应该:

  • 将所有员工插入部门
  • 如果它们存在且未激活,则激活
  • 应停用所有其他员工

创建过程(在 @dep_id INT 中,在 @emp_ids 文本中)

INSERT INTO TBL_DEPARTMENT_EMPLOYEES (DEPARTMENT_ID, EMPLOYEE_ID, IS_ACTIVE) SELECT @dep_id, EMPLOYEE_ID, 1 FROM TBL_EMPLOYEES WHERE FIND_IN_SET(EMPLOYEE_ID, @emp_ids) ON DUPLICATE KEY UPDATE IS_ACTIVE=1;

UPDATE TBL_DEPARTMENT_EMPLOYEES SET IS_ACTIVE=0 WHERE DEPARTMENT_ID=@dep_id 而不是 FIND_IN_SET(EMPLOYEE_ID, @emp_ids);

只有第一个查询运行,我猜第二个查询由于锁定或其他原因而无法运行,我尝试了 TRANSACTION - COMMIT 技巧,没有奏效。我想也许这里有一位很棒的人可以提供帮助,或者 eben 让这一切都在一个查询中运行。谢谢!

4

1 回答 1

2

这个过程并不漂亮,但它是我能想到的最好的给定连接 ID。它也应该比 FIND_IN_SET 解决方案工作得更快,因为它可以使用 EMPLOYEE_ID 上的索引。

CREATE PROCEDURE `test`(IN `dep_id` INT, IN `emp_ids` TEXT)
    LANGUAGE SQL
    NOT DETERMINISTIC
    MODIFIES SQL DATA
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
START TRANSACTION;
IF(emp_ids REGEXP '^[0-9,]+$') THEN #this will NOT guarantee a valid query but will prevent injections
    UPDATE TBL_DEPARTMENT_EMPLOYEES SET IS_ACTIVE=0 WHERE DEPARTMENT_ID=dep_id;
    SET @q = CONCAT('
        INSERT INTO TBL_DEPARTMENT_EMPLOYEES (DEPARTMENT_ID, EMPLOYEE_ID, IS_ACTIVE) 
        SELECT ?, EMPLOYEE_ID, 1 
        FROM TBL_EMPLOYEES 
        WHERE EMPLOYEE_ID IN (',emp_ids,')
        ON DUPLICATE KEY UPDATE IS_ACTIVE=1;
    '); 
    PREPARE stmt1 FROM @q;
    SET @dep_id = dep_id;
    EXECUTE stmt1 USING @dep_id;
    DEALLOCATE PREPARE stmt1;
END IF;
COMMIT;
END ;
于 2013-07-10T16:27:07.000 回答