在oracle中执行存储过程

在oracle中执行存储过程,oracle,plsql,Oracle,Plsql,我需要根据通过提示符传递的值在uu中获取输出 create or replace procedure chklg( uu out logn.username%TYPE , pass in logn.password%TYPE) is begin select username into uu from logn where password=pass; end; 我尝试以这种方式执行上述过程: begin chklg(:p

我需要根据通过提示符传递的值在
uu
中获取输出

create or replace procedure chklg( uu out logn.username%TYPE
                                 , pass in logn.password%TYPE)
is
begin
select username into uu from logn where password=pass;
end; 
我尝试以这种方式执行上述过程:

begin 

chklg(:pass);

end

根据定义,过程不会返回任何内容。你在找一份工作

我对此有点担心,因为它看起来像是将密码存储为纯文本。这不是最佳做法

您应该在用户名旁边存储密码的加盐加胡椒的散列,然后对密码应用相同的加盐加胡椒的散列,并从数据库中选择散列

您可以通过以下两种方式之一执行该函数:

select chklg(:pass) from dual


完整地说,弗兰克·施密特在评论中提出了一个非常有效的观点。除了以非常危险的方式存储密码外,如果两个用户拥有相同的密码,会发生什么情况

您将在
选择到…
中引发太多行异常。这意味着返回给变量的行太多。如果您也传入用户名,那就更好了

这可能会使您的函数看起来如下所示

create or replace function chklg ( 
         p_password_hash in logn.password%type
       , p_username in logn.username%type
          ) return number

   /* Authenticate a user, return 1/0 depending on whether they have
      entered the correct password.
      */

   l_yes number := 0;

begin

   -- Assumes that username is unique.
   select 1 into l_yes 
     from logn
    where password_hash = p_password_hash
      and username = p_username;

   return l_yes;

-- If there-s no username that matches the password return 0.
exception when no_data_found then
   return 0;
end; 

如果您希望只使用一个过程(根本没有真正的理由这样做,因为它不必要地限制了您;您没有执行任何DML),那么您可以获取输出参数,但必须为该过程提供一个可以填充的参数

在你的情况下,它看起来像这样

declare
   l_uu logn.username%type;
begin 
   chklg(l_uu, :pass);
   dbms_output.put_line(l_uu);
end;

这种密码验证方法似乎很奇怪。当两个用户拥有相同的密码时会发生什么?此外,正如Ben提到的,以纯文本传输密码是完全不可能的。提供用户名和密码散列作为参数,并检查它们是否与数据库中存储的值匹配。我不能通过向过程传递值来获取输出参数“uu”的值。。。。
create or replace function chklg ( 
         p_password_hash in logn.password%type
       , p_username in logn.username%type
          ) return number

   /* Authenticate a user, return 1/0 depending on whether they have
      entered the correct password.
      */

   l_yes number := 0;

begin

   -- Assumes that username is unique.
   select 1 into l_yes 
     from logn
    where password_hash = p_password_hash
      and username = p_username;

   return l_yes;

-- If there-s no username that matches the password return 0.
exception when no_data_found then
   return 0;
end; 
declare
   l_uu logn.username%type;
begin 
   chklg(l_uu, :pass);
   dbms_output.put_line(l_uu);
end;