0

我正在玩 MySQL 存储过程,我需要一些帮助来解决一些问题。下面我试图;

1)检查student_id在数据库中是否存在,如果存在则显示“校友已经存在” 2)检查输入的部门和学位参数是否不存在,如果不存在则显示“ _不存在存在”(旁注:这两列是外键)

现在,我的 IF 语句不起作用并引发任意错误。(例如,student_id 在表中不存在,但抛出错误“Alumni Exist Already”,这是其中之一)

我想知道我做错了什么。另外,如果我处理这个问题的方式有意义,如果没有,那么更务实的方式是什么?

谢谢

DELIMITER //
DROP PROCEDURE IF EXISTS sp_add_alumni//

CREATE PROCEDURE sp_add_alumni (
IN  student_id     INT(20),
IN     first_name     VARCHAR(255),
IN     last_name      VARCHAR(255),
IN     street         VARCHAR(255),
IN     city           VARCHAR(255),
IN     state          VARCHAR(2),
IN     zip_code       VARCHAR(15),
IN     email          VARCHAR(255),
IN     telephone      VARCHAR(22),
IN     degree         VARCHAR(255),
IN     department     VARCHAR(255)
)
BEGIN
     DECLARE studentID INT(20);
     DECLARE departmentVAL VARCHAR(255);
     DECLARE degreeVal VARCHAR(255);

     DECLARE EXIT HANDLER FOR SQLWARNING
          BEGIN
               ROLLBACK;
               SELECT 'ALUMNI INSERT HAS FAILED';
          END;


     SET studentID = student_id;
     SET departmentVal = department;
     SET degreeVal = degree;


     IF EXISTS (SELECT 1 FROM alumni WHERE student_id = studentID ) THEN
               SELECT 'ALUMNI ALREADY EXISTS';
     ELSEIF NOT EXISTS (SELECT 1 FROM valid_departments WHERE UCASE(department) = UCASE(departmentVal)) THEN
               SELECT 'DEPARTMENT DOES NOT EXISTS';
     ELSEIF NOT EXISTS (SELECT 1 FROM valid_degrees WHERE UCASE(degree) = UCASE(degreevVal)) THEN
               SELECT 'DEGREE DOES NOT EXISTS';
     ELSE  
              SELECT 'ALUMNI ADDED';
     END IF;

     START TRANSACTION;
        INSERT INTO alumni (student_id, pwd ,first_name, last_name, street, city, state, zip_code, email, telephone, degree, department, role_id, donation_total) VALUES (student_id, NULL ,first_name, last_name, street, city, state, zip_code, email, telephone, degree, department, 1, 0.00);
     COMMIT;
END//
4

1 回答 1

2
  1. 我想知道我做错了什么。

    对存储程序的限制中所述

    存储例程中的名称冲突

    相同的标识符可用于例程参数、局部变量和表列。此外,可以在嵌套块中使用相同的局部变量名称。例如:

    创建过程 p (i INT)
    开始
      DECLARE i INT DEFAULT 0;
      从 t 中选择 i;
      开始
        DECLARE i INT DEFAULT 1;
        从 t 中选择 i;
      结尾;
    结尾;
    

    在这种情况下,标识符不明确,适用以下优先规则:

    • 局部变量优先于常规参数或表列。

    • 例程参数优先于表列。

    • 内部块中的局部变量优先于外部块中的局部变量。

    变量优先于表列的行为是非标准的。

    在您的情况下student_id是例程参数并且studentID是局部变量;因此(考虑到上面的优先规则)过滤器标准WHERE student_id = studentID将这两个东西相互比较,并且在任何时候都不会检查表列。

    由于局部变量设置为例程参数的值,因此此过滤器始终评估为真。

    您可以通过为参数/变量使用不同的名称来避免这种情况,或者通过使用表前缀限定列引用:

    WHERE alumni.student_id = studentID
    
  2. 另外,如果我处理这个问题的方式有意义,如果没有,那么更务实的方式是什么?

    定义合适UNIQUE外键约束,然后尝试插入无效数据将失败,而无需您明确检查任何内容:

    ALTER TABLE alumni
      ADD UNIQUE  KEY (student_id),  -- is this not already a PRIMARY KEY ?
      ADD FOREIGN KEY (department) REFERENCES valid_departments (department),
      ADD FOREIGN KEY (degree    ) REFERENCES valid_degrees     (degree    )
    ;
    

    要使外键使用不区分大小写的查找,请确保各个列使用不区分大小写的排序规则。

    请注意上面链接的文章中外键的限制。

于 2012-10-26T02:00:18.300 回答