我正在玩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//
答案 0 :(得分:2)
我想知道我做错了什么。
正如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
另外,如果我接近这一点的方式是有道理的,如果没有,那么更实用的方法是什么呢?
定义合适的UNIQUE
和foreign 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 )
;
要使外键使用不区分大小写的查找,请确保各列使用不区分大小写的排序规则。
请注意上述链接文章中外键的限制。