我有一个SQL函数应该返回0或1,具体取决于用户激活是否成功。我需要与以下两个表进行交互:
users {user_id, unique email, ...}
user_activation {activation_hash, unique email, ...}
该功能应该评估:
这是我的功能:
delimiter #
create function activate_user
(
p_activation_hash char(32)
)
returns int
deterministic
begin
if not exists (
select 1 from users u
inner join (
select email from user_activation where activation_hash = p_activation_hash
) ua
on u.email = ua.email
)
then
-- hash exists but email doesnt so add
insert into users (email, password_hash, first_name, last_name, company_name)
select email, password_hash, first_name, last_name, company_name
from user_activation
where activation_hash = p_activation_hash
and expiry_date > now();
-- delete the activation row(s)
delete low_priority from user_activation where activation_hash = p_activation_hash;
return 1;
end if;
return 0;
end #
delimiter ;
我的问题是条件总是求值为true(尽管只有1行插入到用户表中,即使没有唯一关键字)。
感谢。
答案 0 :(得分:1)
尝试将定义从DETERMINISTIC
更改为NOT DETERMINISTIC
(或删除它,因为NOT
是默认值),因为该函数的结果不相同给定输入的时间。
一旦使用(有效)哈希,该函数就会为该哈希返回不同的值。您可能反复看到相同的结果,因为第一次调用该函数时它返回1
,现在每次调用它时,即使激活记录不再存在,它也会返回相同的值。哈希的输入可能在一个时刻无效,然后在下一个时间内有效(不太可能)。
有关详细信息,请参阅CREATE PROCEDURE Syntax。
答案 1 :(得分:0)
我今天重新审视了这个问题,发现了一个非常方便的NOT IN查询,它可以解决这个问题:
delimiter #
create procedure activate_user
(
in p_activation_hash char(32),
inout status int
)
proc_main:begin
set status = 0;
if exists (
select 1 from user_activation
where activation_hash = p_activation_hash
and email not in (select email from users)
)
then
-- hash exists but email doesnt so add
insert into users (email, password_hash, first_name, last_name, company_name)
select email, password_hash, first_name, last_name, company_name
from user_activation
where activation_hash = p_activation_hash
and expiry_date > now();
-- delete the activation row(s)
delete low_priority from user_activation where activation_hash = p_activation_hash;
set status = 1;
end if;
end proc_main #
delimiter ;