Inconsistent Insert Results PLSQL [closed] - sql

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a query as shown below:
TRUNCATE TABLE DNARTLOAD;
COMMIT;
.... <Cursor here> .... <do something>.....
tmp_future_phaseA := substr(tmp_phases,1,1);
tmp_future_phaseB := substr(tmp_phases,2,1);
tmp_future_phaseC := substr(tmp_phases,3,1);
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE,FULLPHASE) VALUES
(tmp_load_name, tmp_kvarating, tmp_future_phaseA, tmp_phase);
The problem is that the query fails to insert tmp_phases correctly every time. What I'm doing is taking the substring of temp phases (which is never null) and assigning the first, second, and third character to another set of varchar variables. Once they are assigned, I insert the data into a table and commit. The problem is it doesn't work all the time. It will ALWAYS fill tmp_future_phaseA, B, and C with a character, but when I insert the tmp_phase it will sometimes populate null and sometimes populate the values.
Example Data:
tmp_phase = 'ABC'
tmp_futurephaseA = 'A'
tmp_futurephaseB = 'B'
tmp_futurephaseC = 'C'
Sometimes I'll get the following:
A 'ABC'
B 'ABC'
C 'ABC'
Other times during the same plsql I'll get the following:
A NULL
B NULL
C NULL
EDIT: Added for question:
LOOP
tmp_future_phaseA := NULL;
tmp_future_phaseB := NULL;
tmp_future_phaseC := NULL;
tmp_phases := NULL;
FETCH C3 INTO tmp_load_name, tmp_kvarating, tmp_phases;
EXIT WHEN C3%NOTFOUND;
IF LENGTH(tmp_phases) = 3 THEN
tmp_kvarating := tmp_kvarating / 3;
END IF;
IF LENGTH(tmp_phases) = 2 THEN
tmp_kvarating := tmp_kvarating /2;
END IF;
tmp_future_phaseA := substr(tmp_phases,1,1);
tmp_future_phaseB := substr(tmp_phases,2,1);
tmp_future_phaseC := substr(tmp_phases,3,1);
IF tmp_future_phaseA IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseA);
END IF;
IF tmp_future_phaseB IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseB);
END IF;
IF tmp_future_phaseC IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseC);
END IF;

"Sometimes I'll get the following: ... Other times during the same
plsql I'll get the following:"
Sometimes your program works, sometimes it doesn't. This means you have a data problem.
More accurately, you have written a program which caters correctly for data in some states but not in others. There's absolutely no way we're going to be able to diagnose that.
So, what you need to do is debug your code. If you have a proper IDE that should offer you a debugging facility. Otherwise you will need to use something like DBMS_OUTPUT to display the input for each trip round the loop and the subsequent outcome, so that you can understand which values your program isn't handling correctly.

Related

sql project aid required [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I'm trying to generate a trigger that if a column within a table is filled in with a specific set value e.g. i have a column named 'Volunteertype' which can only be assigned either 'staff' of 'student', if student is entered the trigger must nullify all columns relating to staff details within the volunteer table such as 'area of work', 'staffmanager' etc below is code i have tried to put together utilising the resources on the website however i'm having no luck.
CREATE TRIGGER trg_voltype
ON Volunteer
AFTER INSERT
AS
IF EXISTS (SELECT NULL FROM inserted i WHERE VolunteerType = 'student')
FOR EACH ROW BEGIN;
UPDATE v
SET Area_of_work = NULL
SET StaffManagerName = NULL
SET StaffManagerEmail = NULL
SET StaffManagerPhone = NULL
FROM Volunteer v
JOIN inserted i ON v.Volunteer_id = i.Volunteer_id
WHERE v.VolunteerType = 'student';
END;
However when this is run within the Oracle environment an error is produced ORA-04071: missing BEFORE, AFTER or INSTEAD OF keyword. when i attempt to shift the 'AFTER INSERT' to before the keyword i get an 'invalid trigger' error
Is anyone able to assist and inform me if the code itself is correct/ incorrect and how i should go about amending the code, thanks in advance and have a wonderful end to the year thanks!
Your trigger should be like :
CREATE OR REPLACE TRIGGER trg_voltype
BEFORE INSERT ON volunteer
FOR EACH ROW
BEGIN
if :new.Volunteertype = 'STUDENT'
then
:new.Area_of_work := NULL;
:new.StaffManagerName := NULL;
:new.StaffManagerEmail := NULL;
:new.StaffManagerPhone := NULL ;
end if;
END;

Trigger set insert row values to null [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I'm trying to write a trigger that when something is inserted into the database if it is over a specific time set the row values to null
CREATE OR REPLACE TRIGGER hi
AFTER INSERT OR UPDATE OF CLASS_TIME ON class
FOR EACH ROW
BEGIN
IF (:NEW.CLASS_TIME < '09:00' )
OR (:NEW.CLASS_TIME > '18:00' )
THEN
RAISE_APPLICATION_ERROR(-20000, 'Due to low attendance no class cannot be scheduled at that time');
SET NEW.STAFFNO = NULL;
SET NEW.CLASS_DAY = NULL;
SET NEW.CLASS_TYPE = NULL;
SET NEW.ROOMNUM = NULL;
END IF;
END;
All that I have found online shows that what Ive got is correct but I get the error on the STAFFNO. Thanks in advance for any input.
First of all you have to decide:
either you want the insert or update to fail when it's being done at undesired time
or you want the insert or update to be processed, but with the columns set to null then.
You cannot have both.
In case you want to set the columns to NULL, this should be a BEFORE INSERT/UPDATE trigger, so the changed columns get written to the table. (In an AFTER INSERT/UPDATE trigger setting the fields to some value would not have any effect, becase they are not written.)
Then SET NEW.STAFFNO = NULL; is no valid PL/SQL, that would have to be :NEW.STAFFNO := NULL; instead.
CREATE OR REPLACE TRIGGER hi
BEFORE INSERT OR UPDATE OF class_time ON class
FOR EACH ROW
WHEN (new.class_time NOT BETWEEN '09:00' AND '18:00')
BEGIN
:new.staffno := null;
:new.class_day := null;
:new.class_type := null;
:new.roomnum := null;
END;

Creating trigger which throws an exception on insert

Hello fellow programmers and happy new year to you all!
I have few university tasks for winter break and one of them is to create trigger on table:
PERSON(ID, Name, Surname, Age);
Trigger is supposed to inform user when they have inserted row with invalid ID. Vadility criteria is that ID is 11 digits long.
I tried to write solution like this:
CREATE OR REPLACE TRIGGER person_id_trigg
AFTER INSERT
ON person
DECLARE
idNew VARCHAR(50);
lengthException EXCEPTION;
BEGIN
SELECT id INTO idNew FROM INSERTED;
IF LENGTH(idNew) <> 11 THEN
RAISE lengthException;
END IF;
EXCEPTION
WHEN lengthException THEN
dbms_output.put_line('ID for new person is INVALID. It must be 11 digits long!');
END;
Then I realized that INSERTED exists only in sqlserver and not in oracle.
What would you suggest I could do to fix that?
Thanks in advance!
Do you want to raise an exception (which would prevent the insert from succeeding)? Or do you want to allow the insert to succeed and write a string to the dbms_output buffer that may or may not exist and may or may not be shown to a human running the insert?
In either case, you'll want this to be a row-level trigger, not a statement-level trigger, so you'll need to add the for each row clause.
CREATE OR REPLACE TRIGGER person_id_trigg
AFTER INSERT
ON person
FOR EACH ROW
If you want to raise an exception
BEGIN
IF( length( :new.id ) <> 11 )
THEN
RAISE_APPLICATION_ERROR( -20001,
'The new ID value must have a length of 11' );
END IF;
END;
If you want to potentially print output but allow the insert to succeed
BEGIN
IF( length( :new.id ) <> 11 )
THEN
dbms_output.put_line( 'The new ID value must have a length of 11' );
END IF;
END;
Of course, in reality, you would never use a trigger for this sort of thing. In the real world, you would use a constraint.

Strange runtime behaviour of an update in a cursor

I have an old and a new table. In the old table, there is a VARCHAR2 column, called number, with values like 11-38D402342 and 11-38D402342/43. Also some crappy data, but never null.
In the new table, there are the two VARCHAR2 columns number_left and number_right. these two were filled from the number column of the old table:
number_left = nvl(substr(number,1,instr(number,'/',1)-1),number)
number_right = substr(number,1,instr(rtrim(number,'/'),'/',1)-length(substr(number,instr(number,'/'))))||substr(number,decode(instr(number,'/'),0,null,instr(number,'/')+1))
After some other decisions, we now need only one column again. To make sure the copied numbers get set correctly, I decided to use the number of the old table and the used conversion to identify matching rows.
I have a mapping but cannot use it since the number_left and number_right can be copied into new rows by an application and must get the old number too. So a number of the old table can possibly copied into multible rows in the new table.
I tried used this code:
declare
left_num varchar2(255 char) := '';
right_num varchar2(255 char) := '';
pos number := 0;
CURSOR c_number is
select number from old_table;
begin
for cur in c_number loop
left_num := nvl(substr(cur.number,1,instr(cur.number,'/',1)-1),cur.number);
if instr(cur.number,'/') = 0 then
pos := null;
else
pos := instr(cur.number,'/')+1;
end if;
right_num := substr(cur.number,1,instr(rtrim(cur.number,'/'),'/',1)-length(substr(cur.number,instr(cur.number,'/'))))||substr(cur.number, pos);
update new_table n
set n.number = cur.snummer
where n.number_left = left_num
and (
n.number_right = right_num
or (
n.number_right is null
and right_num is null
)
);
end loop;
end;
In the old table I have 170.000 lines and in the new one 180.000 since there is also some new data. Peanuts.
But here comes the strange part:
Everything seems to work fine but after the first 14.000 rows it gets terribly slow, perhaps 3 rows in a second. And I think it becomes slower and slower.
Any idea?
Instead of asking a bunch of random starngers to take a guess you should learn how to trace the performance of SQL in the database. There are several differnt ways you can gain insight into the performance of your statement, but you will ned some level of DBA-type access.
This is an area which is covered in the official documentation but I suggest you start with Tim Hall's excellent overview. Find it here.

Function to verify username and password in pl/sql [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I've got a table called BANKCUSTOMER with the following columns:
USERNAME NOT NULL VARCHAR2(11)
FAMILY_NAME NOT NULL VARCHAR2(25)
NAME NOT NULL VARCHAR2(25)
PASSWD NOT NULL VARCHAR2(6)
I want to make a function which checks in the database if the users USERNAME and PASSWORD matches the data in the database. If the login succeeds then it should print out "Login successful!" otherwise "Wrong username or password!"
I visited a pl/sql tutorial site and came over the following code which i modified a bit so it can work with my database, but there is something I don't understand and that is what z number does and what begin select 1 into z does. Could someone please explain that for me.
create or replace function log_in(x in varchar2, y in varchar2)
return varchar2
as
z number;
begin
select 1
into z
from bankcustomer
where username=x
and passwd=y;
dbms_output.put_line('Login successful!');
exception
when no_data_found then
dbms_output.put_line('Wrong username or password!');
end;
I would like to test the function by writing SELECT log_in() FROM dual; to see if it works. When I write SELECT log_in() FROM dual; I get an error message saying:
Error starting at line 1 in command:
SELECT log_in() FROM dual
Error at Command Line:1 Column:7
Error report:
SQL Error: ORA-06553: PLS-306: wrong number or types of arguments in call to 'LOG_IN'
06553. 00000 - "PLS-%s: %s"
*Cause:
*Action:
How can this be resolved?
You have defined a function but do not return a value from it. Given the fact that you "select" the function there is no need to use dbms_output:
create or replace function log_in(x in varchar2, y in varchar2)
return varchar2
as
match_count number;
begin
select count(*)
into match_count
from bankcustomer
where username=x
and passwd=y;
if match_count = 0 then
return 'Wrong username or password!';
elsif match_count = 1 then
return 'Login successful!';
else
return 'Too many matches, this should never happen!';
end if;
end;
/
Additionally your call to the function does not provide the username and password parameters, that's why you get the error message. Assuming you have changed the function to actually return something, you need to use
SELECT log_in('username', 'secretpassword') FROM dual;
Have you actually passed any arguments to the log_in function? And what is logga_in()? Is the latter a typo on your side?
Anyway, the select 1 into z only forces an exception in case no match is found. Nothing more.
In other words, you could write the code without it, for example with select count(*) into authenticated ... and then you could check if authenticated != 0 and do the appropriate action. I don't have an Oracle instance so this code is written blindly, you'll need to test it:
create or replace function log_in(x in varchar2, y in varchar2)
return varchar2
as
match_count number;
begin
select count(*)
into match_count
from bankcustomer
where username=x
and passwd=y;
if match_count = 0 then
dbms_output.put_line('Wrong username or password!');
elsif match_count = 1 then
dbms_output.put_line('Login successful!');
else
dbms_output.put_line('Too many matches, this should never happen!');
end;
Just to add more information to what's already been provided, the BEGIN keyword indicates the beginning of the execution block; what's above that is the function header and any declaration statements.
The statement z number; is a variable declaration statement declaring a variable that is named z and is of the datatype number. The SELECT 1 INTO z WHERE... statement is checking the BANKCUSTOMER table for a row where the username matches what's passed to the function in the first parameter, and a password that matches what's passed to the function in the second parameter.
If there is a row where the username and password match what's passed to the function, then the variable z will contain the number 1. If there isn't, the Oracle NO_ROWS_FOUND exception will be raised, because SELECT...INTO statements must always select one and only one row, or else they will raise an exception (the NO_ROWS_FOUND exception for no rows, and the TOO_MANY_ROWS exception for more than one row).
Hope that's helpful! Don't hesitate to ask if you have more questions.