在MySQL存储过程中抛出自定义错误

时间:2012-10-26 01:26:36

标签: mysql stored-procedures

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

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

现在,我的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//

1 个答案:

答案 0 :(得分:2)

  1.   

    我想知道我做错了什么。

    正如Restrictions on Stored Programs所述:

      

    存储例程中的名称冲突

         

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

    CREATE PROCEDURE p (i INT)
    BEGIN
      DECLARE i INT DEFAULT 0;
      SELECT i FROM t;
      BEGIN
        DECLARE i INT DEFAULT 1;
        SELECT i FROM t;
      END;
    END;
    
         

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

         
        
    • 局部变量优先于例程参数或表列。

    •   
    • 例程参数优先于表列。

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

    •   
         

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

    在您的情况下,student_id是一个例程参数,studentID是一个局部变量;因此(根据上面的优先规则),过滤标准WHERE student_id = studentID正在将这两个事物相互比较,并且不会检查表格列。

    由于局部变量设置为例程参数的值,因此此过滤器始终的计算结果为true。

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

    WHERE alumni.student_id = studentID
    
  2.   

    另外,如果我接近这一点的方式是有道理的,如果没有,那么更实用的方法是什么呢?

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

    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    )
    ;
    

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

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

相关问题