Oracle 如何使用函数在PL/SQL表中添加新用户?
我对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,
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是正确的,这是一个非常糟糕的函数用法。然而,功能是您的任务的要求
因此,让我们剖析您的代码,看看它如何满足您的每一个需求。(我受不了所有的帽子,所以我把它放低了。)
免责声明:由于您未发布表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;