Reputation: 29
I am new to using Oracle, and I am trying to create an add/insert stored procedure for a table. The PROD_CD and PLAN_CD fields in my table can have no value (empty or null) Can you please check my code and let me know what I am doing wrong?
CREATE TABLE DCWEB.USER_PLAN_PREFERENCE
(
USERID VARCHAR2(40) NOT NULL,
PROD_CD VARCHAR2(9) NULL,
PLAN_CD VARCHAR2(9) NULL,
STATE_LST VARCHAR2(2) NOT NULL,
STATE_NM VARCHAR2(40) NOT NULL,
LST_UPDATE_TS TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL
);
ALTER TABLE DCWEB.USER_PLAN_PREFERENCE
ADD CONSTRAINT USER_PLAN_PREFERENCE_XPK PRIMARY KEY (USERID, PROD_CD, PLAN_CD);
-- Grant/Revoke object privileges
grant select, insert, update, delete on DCWEB.USER_PLAN_PREFERENCE to HIGGIB1;
procedure setUserPlanPref (
userid in varchar2,
prod_cd in varchar2,
plan_cd in varchar2,
state_lst in varchar2,
state_nm in varchar2
)
is
currentTimestamp timestamp := current_timestamp;
begin
insert into user_plan_preference (userid, prod_cd, plan_cd, state_lst, state_nm, lst_update_ts)
values (upper(userid), upper(prod_cd), upper(plan_cd), upper(state_lst), upper(state_nm), currentTimestamp);
commit;
exception
when dup_val_on_index then
begin
update user_plan_preference up set
up.userid = upper(userid),
up.prod_cd = upper(prod_cd),
up.plan_cd = upper(plan_cd),
up.state_lst = upper(state_lst),
up.state_nm = upper(state_nm),
up.lst_update_ts = currentTimestamp
where up.userid = upper(userid)
and up.prod_cd = upper(prod_cd)
and up.plan_cd = upper(plan_cd);
commit;
exception
when others then
rollback;
end;
when others then
rollback;
end;
end;
I am unable to insert a record calling the stored procedure with values: DCWEB4578, , 2P, CA, CALIFORNIA but when I change to the string "NULL", the insert succeeds. When I try to call the stored procedure to update the inserted record with values: DCWEB4578, "NULL", 2P, CO, COLORODO the update does not happen since I still see the original record in the table.
Upvotes: 2
Views: 8502
Reputation: 231671
Your immediate problem is that if you include PROD_CD
and PLAN_CD
in the primary key, the primary key constraint is going to require that both columns are NOT NULL
. You can either allow NULL
values in those columns or you can include them in the primary key but not both.
This would have been clearer to you had your exception handlers not been written to swallow exceptions. It is almost always a bug waiting to happen when you code something like this
when others then
rollback;
end;
If you are going to have a when others
exception handler, you almost always want to at least re-raise the exception.
when others then
rollback;
raise;
end;
Otherwise, the caller has no idea that an error occurred and has no idea what the error was. Had you re-raised the exception, you would have seen something like
ORA-01400: cannot insert NULL into ("DCWEB"."USER_PLAN_PREFERENCE"."PROD_CD")
which would at least have pointed you in the right direction and would have given you something to post here.
Additionally, declaring parameters that have the same name as columns in your tables is another error waiting to happen. You really want to adopt some sort of convention to differentiate parameter names from column names. Personally, I prefix parameter names with p_
, i.e. p_userid in varchar2,
. Otherwise, your code will almost certainly not do what you expect.
Since column names have precedence over local variables when you are executing a SQL statement, your UPDATE
statement resolves upper(userid)
, upper(prod_cd)
, etc to the columns in the USER_PLAN_PREFERENCE
table not to the parameters that have been passed in. Assuming your data is always in upper case, this UPDATE
statement will update every row of USER_PLAN_PREFERENCE
, not just the one row you expect to update, and it will set every row's LST_UPDATE_TS
to currentTimestamp
.
update user_plan_preference up
set up.userid = upper(userid),
up.prod_cd = upper(prod_cd),
up.plan_cd = upper(plan_cd),
up.state_lst = upper(state_lst),
up.state_nm = upper(state_nm),
up.lst_update_ts = currentTimestamp
where up.userid = upper(userid)
and up.prod_cd = upper(prod_cd)
and up.plan_cd = upper(plan_cd);
If your naming convention differentiates column names and parameter names, it would be much harder to inadvertently use a column name when you intended to use a parameter or local variable name.
Upvotes: 1
Reputation: 9581
the problem is here
if you want a col to not accept null values you define it as NOT NULL and vice versa
CREATE TABLE DCWEB.USER_PLAN_PREFERENCE
(
USERID VARCHAR2(40) NOT NULL,
PROD_CD VARCHAR2(9) NULL,--**this should be NOT NULL**
PLAN_CD VARCHAR2(9) NULL,--**this should be NOT NULL**
STATE_LST VARCHAR2(2) NOT NULL,
STATE_NM VARCHAR2(40) NOT NULL,
LST_UPDATE_TS TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL
);
Upvotes: 0