Oracle 如何使用函数在PL/SQL表中添加新用户?

Oracle 如何使用函数在PL/SQL表中添加新用户?,oracle,plsql,Oracle,Plsql,我对PL/SQL相当陌生,我的疑问之一是创建和声明函数。 具体来说,这一点: 创建创建新用户的函数: 使用序列为新用户提供新ID 传递姓名、地址等。。。在争论中 将创建的ID和O_错误消息作为OUT参数返回 如果添加了用户,则函数返回TRUE,否则返回FALSE 处理异常 创建PL/SQL块并测试创建的函数 这是我目前的代码: CREATE OR REPLACE FUNCTION DSB_ADD_NEW_USERS (I_NAME IN VARCHAR2,

我对PL/SQL相当陌生,我的疑问之一是创建和声明函数。 具体来说,这一点:

创建创建新用户的函数:

  • 使用序列为新用户提供新ID
  • 传递姓名、地址等。。。在争论中
  • 将创建的ID和O_错误消息作为OUT参数返回
  • 如果添加了用户,则函数返回TRUE,否则返回FALSE
  • 处理异常
  • 创建PL/SQL块并测试创建的函数
  • 这是我目前的代码:

    
    CREATE OR REPLACE FUNCTION DSB_ADD_NEW_USERS (I_NAME IN VARCHAR2,
                                                    I_ADDRESS IN VARCHAR2,
                                                    I_BIRTHDATE IN DATE,
                                                    I_COUNTRY IN VARCHAR2)
        RETURN NUMBER IS
        O_ERROR_MESSAGE EXCEPTION;
        CURRENT_USER NUMBER;
    
    BEGIN
    
    DSB_NB_SEQ_USER_ID.NEXTVAL;
    SELECT COUNT(USER_ID) INTO CURRENT_USER
    FROM DSB_NB_USERS;
    
    WHILE CURRENT_USER != 0
    LOOP
    DSB_NB_SEQ_USER_ID.NEXTVAL;
    SELECT COUNT(USER_ID) INTO CURRENT_USER
    FROM DSB_NB_USERS;
    END LOOP;
    
    INSERT INTO DSB_NB_USERS (USER_ID, NAME, ADDRESS, BIRTHDATE, COUNTRY_ID_FK) VALUES (CURRENT_USER, I_NAME, I_ADDRESS, TO_DATE('I_BIRTHDATE', 'DD/MM/YYYY'), I_COUNTRY);
    
    RETURN CURRET_USER;
    
    EXCEPTION
        WHEN O_ERROR_MESSAGE THEN 
        RETURN NULL;
    
        WHEN OTHERS THEN
        RETURN NULL;
    END;
    
    DECLARE
        I_NEW_USER NUMBER;
    BEGIN
        I_NEW_USER := DSB_ADD_NEW_USERS(I_NAME => 'Arnaldo Amaral',
                                        I_ADDRESS => 'Rua da Agra',
                                        I_BIRTHDATE => '03/05/1959',
                                        I_COUNTRY => 'PT');                                 
    END;
    
    
    
    我是不是离真相太远了? 我知道还有很多要补充


    谢谢你的帮助

    为什么不直接使用序列值插入新用户,如下所示:

    CREATE OR REPLACE FUNCTION DSB_ADD_NEW_USERS (
        I_NAME        IN            VARCHAR2,
        I_ADDRESS     IN            VARCHAR2,
        I_BIRTHDATE   IN            DATE,
        I_COUNTRY     IN            VARCHAR2
    ) RETURN NUMBER IS
        CURRENT_USER_ID   NUMBER;
    BEGIN
        CURRENT_USER_ID := DSB_NB_SEQ_USER_ID.NEXTVAL; -- returns new and unique number
        INSERT INTO DSB_NB_USERS (
            USER_ID,
            NAME,
            ADDRESS,
            BIRTHDATE,
            COUNTRY_ID_FK
        ) VALUES (
            CURRENT_USER_ID,
            I_NAME,
            I_ADDRESS,
            I_BIRTHDATE,
            (
                SELECT
                    COUNTRY_ID
                FROM
                    COUNTRIES
                WHERE
                    NAME = I_COUNTRY
            ) -- it is FK so need to use SELECT sub-query to find COUNTRY_ID
        );
    
        RETURN CURRENT_USER_ID; -- returning the new user ID
    EXCEPTION
        WHEN OTHERS THEN
            RETURN -1; -- returning -1 in case there is any error
    END;
    

    -当添加新用户时出现错误时,将返回1。

    在向一些人寻求帮助后得出了这个更简单的答案

    create or replace FUNCTION DSB_ADD_NEW_USERS (I_NAME IN VARCHAR2,
                                                    I_ADDRESS IN VARCHAR2,
                                                    I_BIRTHDATE IN DATE,
                                                    I_COUNTRY IN VARCHAR2)
        RETURN NUMBER IS
        CURRENT_USER NUMBER;
    
    BEGIN
    CURRENT_USER := DSB_NB_SEQ_USER_ID.NEXTVAL;
    DBMS_OUTPUT.PUT_LINE('Hello World');
    
    INSERT INTO DSB_NB_USERS (USER_ID, NAME, ADDRESS, BIRTHDATE, COUNTRY_ID_FK) VALUES (CURRENT_USER, I_NAME, I_ADDRESS, TO_DATE(I_BIRTHDATE, 'DD/MM/YYYY'), I_COUNTRY);
    RETURN CURRENT_USER;
    
    EXCEPTION
        WHEN OTHERS THEN 
        RETURN -1;
    
    END;
    
    SET SERVEROUT ON
    DECLARE
        I_NEW_USER NUMBER;
    BEGIN
        I_NEW_USER := DSB_ADD_NEW_USERS(I_NAME => 'Arnaldo Amaral',
                                        I_ADDRESS => 'Rua da Agra',
                                        I_BIRTHDATE => '03/MAY/1959',
                                        I_COUNTRY => 'PT');       
                                        commit;
    
    
    END;
    /
    

    谢谢大家

    在我看来,您要求的是一条生命线,它需要的不仅仅是代码响应。首先看下面的答案 @特贾什。他的解决方案与您的解决方案相去甚远,并且对于您的函数定义是正确的(尽管考虑到您列出的需求,这本身是不正确的。)此外,@EdStevens是正确的,这是一个非常糟糕的函数用法。然而,功能是您的任务的要求
    因此,让我们剖析您的代码,看看它如何满足您的每一个需求。(我受不了所有的帽子,所以我把它放低了。)

  • 失败了。虽然您有一个序列,但它使用不当。你不能 只需编写一个独立的名称。它必须在SQL或SQL中使用 语句或赋值语句
  • 通行证
  • 失败了。您的函数正确地传入参数。然而 没有输出参数
  • 函数返回的数字不是所需的真/假 需要布尔值或varchar2作为文字

    要求3,4的代码部分


  • 免责声明:由于您未发布表DDL或测试数据,因此例程未经测试,甚至未编译。任何语法错误都由您自行解决。此外,我遵循Tejash的假设,假设您实际上有一个国家表,并且有一个FK。这可能是一个错误的假设。

    其他人可能不同意,但我不认为这是一个很好的使用函数。我认为它更适合一个程序。当我想到函数的时候,我想到的是像。。。返回单个值并打算将该单个值指定给正确类型的变量或作为查询的列投影的一部分。我希望作业指定专门调用函数。@WilliamRobertson-是的,不幸的是,这是我/我们在所有技术论坛上看到的。在学校作业中寻求帮助的人,该作业可能旨在教授一种非常具体的编码技术,但也教授糟糕的设计实践。教师无法理解,当他们给学生一个练习来教授(比如“循环光标”时),学生缺乏任何其他背景,也在学习给定练习的上下文,并假设它是可接受的应用程序/系统设计。@EdStevens,这确实是一个家庭作业请求。你不是第一个说同样话的人。我试图从我的老师那里挤出更多的知识,但是由于这次流感和其他20名学生复习代码,这变得有点困难。我正在学习一套新技能,犯下这些错误是学习它的最好方法,因为这样你就会知道什么是不该做的。尽管如此,我认为这可能是一个带有陷阱的问题,这不是老师第一次这样做。再次感谢您的帮助!值得一提的是,没有参数的函数被广泛认为是不好的做法。这是一个巨大的危险信号,这应该是一个程序。保护者,非常感谢你的投入。不需要道歉或感到震惊,我只是复制粘贴此评论。那不是我的本意。我真的想并且需要理解这一点。谢谢你“糟蹋”我的工作,让我学会更好的做法。我将继续研究这段代码,试图理解我在哪里犯了错误并解决它们。再次非常感谢您!:-)任务完成:-)
    create or replace function dsb_add_new_users (i_name in varchar2,
                                                  i_address in varchar2,
                                                  i_birthdate in date,
                                                  i_country in varchar2)   <<< where are the 2 required out parameters
        return number is                                                   <<< Should be True or False so either Boolean or varchar2
        o_error_message exception;                                         <<< Should be an Out parameter not an exception
    
    exception
        when o_error_message then      <<< as coded this is a developer defined exception, yet is not raised so it cannot happen.
        return null;                   <<< even if it were raised you have thrown it away, the calling routine will never it happened
    
        when others then               <<< One of the worst pieces of code that can be written. I tend to remember seeing a discussion in 
        return null;                   <<< Oracle that would make this a compile time error. To bad the supporters lost the argument.                                                                                       
    
    current_user number;   <<< NO, NO bad verifiable name.
    
    dsb_nb_seq_user_id.nextval;                <<< systax error. 
    select count(user_id) into current_user    <<< count the number of rows in the table
    from dsb_nb_users;
    
    while current_user != 0                    <<< if there are any rows in the table 
    loop
    dsb_nb_seq_user_id.nextval;                <<< syntax  error 
    select count(user_id) into current_user    <<< try counting then again until there are none.
    from dsb_nb_users;
    end loop;
    
    create or replace function dsb_add_new_users 
                             ( i_name          in  varchar2
                             , i_address       in  varchar2
                             , i_birthdate     in  date
                             , i_country       in  varchar2
                             , o_new_user_id   out number
                             , o_error_message out varchar2
        return boolean 
    is
        country_id_l  number;
    begin
       -- initialize out variables
       o_new_user_id   := null;
       o_error_message := null;
    
       -- get country id from input parameter
       select country_id 
         into country_id_l
         from country
        where name = i_country;
    
       -- create user and get the assigned user_id
    
        insert into dsb_nb_users (user_id, name, address, birthdate, country_id_fk) 
             values dsb_nb_seq_user_id.nextval
                  , i_name
                  , i_address
                  , i_birthdate
                  , country_id_l
                  )
          returning user_id
               into o_new_user_id;
    
        return true;
    
    exception
        when no_date_found then 
            o_output_message = 'ERROR: Specified country name ''' || country_id_l || ''' Not Found.';
            return false;
    
        when others then
            o_output_message := 'ERROR: ' || sqlerrm;
            return false
    end dsb_add_new_users ;
    
    
    --------------- Test Driver ----------------
    declare
        i_new_user       number;
        new_user_created boolean;
        error_message    varchar2(255);     
    begin
        new_user_created := dsb_add_new_users( i_name          => 'Arnaldo Amaral',
                                             , i_address       => 'Rua da Agra' 
                                             , i_birthdate     => to_date('03/05/1959','mm/dd/yyyy')  -- or is it 'dd/mm/yyyy' 
                                             , i_country       => 'PT'
                                             , o_new_user_id   => i_new_user
                                             , o_error_message => error_message);
       if not new_user_created
       then 
           dbms_output.put_line (error_messag); 
       end if ; 
    end;