问题
In my Oracle PL/SQL procedure I am trying to update a row like this:
UPDATE personal p
SET p.surname = surname, p.name = name, p."alter" = alter, p.sex = sex, p.jobcode = jobcode, p.year_wage = month_wage * 12
WHERE p.personalnr = personalnr;
COMMIT;
I have added these two statements right after the commit to confirm the code is reached and executed with the right arguments (e.g. here I want to change the name):
DBMS_OUTPUT.put_line('updated ' || name);
DBMS_OUTPUT.put_line('personalnr ' || personalnr);
Now this update-statement is part of a procedure that is called from within another procedure.
However, the changes are not applied and the name will remain the same even tho the update was executed. I have tried to use an exception-handler as well and there doesn't seem to be any exception happening. I can confirm that the WHERE
-clause is as intendet. There is one record that matches the predicate.
Now the strange thing:
When I change the code to the example below, an update happens. However it updates every record and not only the one with the right personalnr. Again: the routine is called only once with one personalnr
that matches only one entry in the table.
UPDATE personal p
SET p.name = 'test'
WHERE p.personalnr = personalnr;
COMMIT;
回答1:
It is working, but it's updating all rows in the table (or at least, those where personalnr
is not null), not just the one you expect.
From the documentation:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
You have a PL/SQL variable that has the same name as a column. When you do
where p.personalnr = personalnr
you are really doing:
where p.personalnr = p.personalnr
and the same thing happens in the set
part; SET p.surname = surname
updates the column value to whatever value it had before, not the PL/SQL variable's value. So it looks like the update didn't happen- it actually did, but because everything was set to the same as it's original value it doesn't look like anything happened. (Except - all rows will now have the same year_wage
value...)
You can either prefix your variables with the procedure name:
where p.personalnr = my_proc.personalnr
or change the variable names so they don't conflict; it's common to use a short prefix, e.g. l_
for a local variable, or p_
for a passed-in parameter, etc.
where p.personalnr = l_personalnr
Remember to do that for the set
part too, or your update still won't appear to do anything.
UPDATE personal p
SET p.surname = l_surname, p.name = l_name, p."alter" = l_alter,
p.sex = l_sex, p.jobcode = l_jobcode, p.year_wage = l_month_wage * 12
WHERE p.personalnr = l_personalnr;
回答2:
You need to change the parameter name something other than the table's column name.
UPDATE personal p
SET p.name = 'test'
WHERE p.personalnr = personally;
-- here condition is column_name = column_name
-- This will be true for all the records of the table
Change personalnr --> p_personalnr
and it will work for you
来源:https://stackoverflow.com/questions/62595392/oracle-update-from-within-procedure-not-working