MySQL函数条件总是证明是真的

时间:2012-09-11 22:54:08

标签: mysql function conditional evaluate

我有一个SQL函数应该返回0或1,具体取决于用户激活是否成功。我需要与以下两个表进行交互:

users {user_id, unique email, ...}
user_activation {activation_hash, unique email, ...}

该功能应该评估:

  1. 传入哈希是否与user_activation中的行匹配?
  2. 用户表中是否还没有相应的电子邮件?
  3. 然后将新用户插入用户并删除激活行并返回1,否则返回0
  4. 这是我的功能:

    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行插入到用户表中,即使没有唯一关键字)。

    感谢。

2 个答案:

答案 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 ;