Null value return problem - database

I wanted to check my monthly payroll in which there are employee salary along with other detail.
I have created a PL/SQL block but when I place my condition for checking of existing employee id with another table some return null value and hence my table does not go further.
set serveroutput on
declare
emp_id NUMBER :=&emp;
temp NUMBER;
begin
select nvl(employee_id,10) into temp FROM bhavya_temp where bhavya_temp.employee_id=emp_id;
dbms_output.put_line(temp);
if temp is NULL
then
dbms_output.put_line('employee ID does not exist');
else
dbms_output.put_line('bye');
end if;
end;
When I enter employee id 1 or 2 which exist in table the result is
anonymous block completed
1
bye
When I enter 3 or more which is not there
Error report:
ORA-01403: no data found
ORA-06512: at line 6
01403. 00000 - "no data found"
*Cause:
*Action:
Thanks for help in advance.

I've never written any PL/SQL, but a very similar error is reported here.
It looks like you can handle the problem by placing the SELECT ... INTO portion inside of a BEGIN ... EXCEPTION .. END block.
Hope this helps.

It would be helpful to have the create table statements with some example data, so that the problem can be reproduced.
To the question : If the row with the ID does not exist vou get the ORA-1403 . There is no data, there is no NULL to convert. Oracle does not dream a row up for you.

Wrap your select stament in an exception block and catch the 'no data found' exception, and act accordingly

Related

SP2-0552: Bind variable "NEW" not declared and END Error report - Unknown Command

I have to write a trigger for the tables I made and in insert update, I have to record a separate log table for those that are updated or inserted.
Columns in the log table will be like;
Done_process (will write update, insert)
Person (student number of the person treated)
Before (previous value for update, blank for insert)
After (new value for update, new value for insert)
This is my student_info table,
CREATE TABLE student_info (
school_id NUMBER,
id_no NUMBER NOT NULL UNIQUE,
name VARCHAR2(50) NOT NULL,
surname VARCHAR2(50) NOT NULL,
city VARCHAR2(50) NOT NULL,
birth_date DATE NOT NULL,
CONSTRAINT student_info_pk PRIMARY KEY(school_id )
);
CREATE TABLE og_log(
done_process VARCHAR2(30),
person VARCHAR2(30),
before VARCHAR2(30),
after VARCHAR2(30)
);
CREATE OR REPLACE TRIGGER og_trigger
BEFORE INSERT OR UPDATE OR DELETE ON student_info
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
ENABLE
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Insert',:new.school_id,:old.name,:new.name);
ELSIF UPDATING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Update',:new.school_id,:old.name,:new.name);
END IF;
END;
/
When I try to run the code it gave an error as follows;
> Trıgger OG_TRIGGER created.
>
>
> Error starting at line : 280 in command - ELSIF UPDATING THEN Error
> report - Unknown Command
>
> SP2-0552: Bind variable "NEW" not declared.
>
> 0 rows inserted.
>
>
> Error starting at line : 283 in command - END IF Error report -
> Unknown Command
>
> SP2-0044: For a list of known commands enter HELP and to leave enter
> EXIT.
>
> Error starting at line : 284 in command - END Error report - Unknown
> Command
I believe you are creating this trigger for learning purpose and not something a real use case because what you do in trigger doesn't really making any sense.
The trigger you have mentioned is not compiling due to syntactical problems like where v_id := 20201033.
Where clause is used to compare the value and thus you should use = instead := which is an assignment operator.
Besides this problem few points which still needs to be taken care
Give a explicit convention for creating local variables. e.g. you have created a local variable v_id and the same column is also available in student_info table. Though it is not a problem in this case but it's good practice to keep the local variable specific like let's say l_v_id.
You have used a select statement inside trigger which could leads to NO_DATA_FOUND error and you should handle it by either in the exception section or another way would be using aggregate function like max() if obviously v_id is primary key. I doubt why you need this select statement ( you could use between old and new using something like coalesce(:old.school_id,:new_schoold_id) if I understood you) but I would leave it open to you to decide and act accordingly.
Considering above points final code will be,
CREATE OR REPLACE TRIGGER og_trigger
BEFORE INSERT OR UPDATE OR DELETE ON student_info
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
ENABLE
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Insert',:new.school_id,:old.city,:new.city);
ELSIF UPDATING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Update',:new.school_id,:old.city,:new.city);
END IF;
END;
/
Find demo db<>fiddle
EDITED: Solving probably tool issue
I doubt the issue is with SQL Developer tool usage , however last try i would like to make,
Step1:
Drop both the tables used by issuing drop command
drop table STUDENT_INFO;
drop table og_log;
Step2:
Open another SQL worksheet using alt+F10 and do as I have shown in the following image. Please try and let me know.

Missing Insert Record on the table with Trigger (Oracle DB)

The scenario is the following -
OrderTable with Columns "OrderId" and "OrderType"
OrderRelationTable with Columns "OrderId" and "CustId"
OrderProcessTable with Columns "OrderId", "OrderType", "CustId", and "ProcessFlag"
The flow goes like this-
Application1 creates the record in OrderTable -> Then pass the record to Application2 by using MQ protocol, Application 2 in this case insert/create the record passed in the OrderRelationTable -> Then a trigger is called in Oracle DB to create the record in OrderProcessTable
Problem
Sometimes the record is not inserted into table 3 OrderProcessTable. Not sure if it is cause by timing or there is something that is not correct with the trigger?
Application1 Code
boolean updated = false;
/** JDBC prepare statement execution insert into OrderTable in Java**/
int rowCount = ps.executeUpdate();
if(rowCount>0){
updated=true;
}
log.log("updated flag:"+updated);
/** I am able to see the log shows the flag is true, and recored inserted into OrderTable **/
Application2 Code
This doesn't really matter much assuming that it is some Java JDBC code that does the insert into OrderRelationTable and it is successful.
The Trigger
Assuming the syntax is correct.
CREATE OR REPLACE TRIGGER INSERTINTOOrderProcessTable
AFTER INSERT ON OrderRelationTable
FOR EACH ROW DECLEAR
v_order_type := null;
BEGIN
SELECT OrderType INTO v_order_type FROM OrderTable
WHERE OrderId = :new.OrderId
AND OrderType IS NOT NULL
AND rownum=1;
IF v_order_type IS NOT NULL THEN
INSERT INTO OrderProcessTable VALUES (:new.OrderId, v_order_type, :new.CustId, 'N');
END IF;
END;
Questions -
After the Application 1 Code is executed is guaranteed DB will have the OrderTable record avaliable for SELECT statement? (Assume that updated flag is true)
Is there a timing issue with the app code and trigger? for example when trigger calls the SELECT statement from OrderTable? (of course the order id is matching in the OrderRelationTable and OrderTable)
Basically right now my problem is that sometimes (rarely) the record is not inserted into OrderProcessTable via the trigger even though it should (Order Type is not null)? Any idea?
There's no timing issue, as far as I can tell.
As of trigger code: what is the purpose of and rownum = 1 condition? I'm not saying that it is wrong, I'm just asking. Do you expect several rows to be returned by that query? If so, is that a legal situation? Wouldn't you rather handle it with the WHEN TOO_MANY_ROWS exception handler (i.e. instead of using the ROWNUM condition)?
What happens if SELECT returns nothing? It raises then NO_DATA_FOUND exception and trigger fails and certainly doesn't insert anything. Is it propagated so that someone (human being) or something (error logging procedure) sees / catches it so that you'd know that something went wrong?
And, of course, the fact that V_ORDER_TYPE remains NULL which causes INSERT to fail (as P. Salmon already suggested).

Avoid Adding Duplicate Records

I m trying to write if statement to give error message if user try to add existing ID number.When i try to enter existing id i get error .untill here it s ok but when i type another id no and fill the fields(name,adress etc) it doesnt go to database.
METHOD add_employee.
DATA: IT_EMP TYPE TABLE OF ZEMPLOYEE_20.
DATA:WA_EMP TYPE ZEMPLOYEE_20.
Data: l_count type i value '2'.
SELECT * FROM ZEMPLOYEE_20 INTO TABLE IT_EMP.
LOOP AT IT_EMP INTO WA_EMP.
IF wa_emp-EMPLOYEE_ID eq pa_id.
l_count = l_count * '0'.
else.
l_count = l_count * '1'.
endif.
endloop.
If l_count eq '2'.
WA_EMP-EMPLOYEE_ID = C_ID.
WA_EMP-EMPLOYEE_NAME = C_NAME.
WA_EMP-EMPLOYEE_ADDRESS = C_ADD.
WA_EMP-EMPLOYEE_SALARY = C_SAL.
WA_EMP-EMPLOYEE_TYPE = C_TYPE.
APPEND wa_emp TO it_emp.
INSERT ZEMPLOYEE_20 FROM TABLE it_emp.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'INFO'
TEXTLINE1 = 'Record Added Successfully.'.
elseif l_count eq '0'.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'INFO'
TEXTLINE1 = 'Selected ID already in database.Please type another ID no.'.
ENDIF.
ENDMETHOD.
I'm not sure I'm getting your explanation. Why are you trying to re-insert all the existing entries back into the table? You're just trying to insert C_ID etc if it doesn't exist yet? Why do you need all the existing entries for that?
If so, throw out that select and the loop completely, you don't need it. You have a few options...
Just read the table with your single entry
SELECT SINGLE * FROM ztable INTO wa WITH KEY ID = C_ID etc.
IF SY-SUBRC = 0.
"this entry exists. popup!
ENDIF.
Use a modify statement
This will overwrite duplicate entries with new data (so non key fields may change this way), it wont fail. No need for a popup.
MODIFY ztable FROM wa.
Catch the SQL exceptions instead of making it dump
If the update fails because of an exception, you can always catch it and deal with exceptional situations.
TRY .
INSERT ztable FROM wa.
CATCH sapsql_array_insert_duprec.
"do your popup, the update failed because of duplicate records
ENDTRY.
I think there's a bug when appending in internal table 'IT_EMP' and inserting in 'ZEMPLOYEE_20' table.
Suppose you append the first time and then you insert. But when you append the second time you will have 2 records in 'IT_EMP' that are going to be inserted in 'ZEMPLOYEE_20'. That is because you don't refresh or clear the internal table and there you will have a runtime error.
According to SAP documentation on 'Inserting Lines into Tables ':
Inserting Several Lines
To insert several lines into a database table, use the following:
INSERT FROM TABLE [ACCEPTING DUPLICATE KEYS] . This
writes all lines of the internal table to the database table in
one single operation. The same rules apply to the line type of
as to the work area described above. If the system is able to
insert all of the lines from the internal table, SY-SUBRC is set to 0.
If one or more lines cannot be inserted because the database already
contains a line with the same primary key, a runtime error occurs.
Maybe the right direction here is trying to insert the work area directly but before you must check if record already exists using the primary key.
Check the SAP documentation on this issue clicking the link before.
On the other hand, once l_count is zero because of l_count = l_count * '0'. that value will never change to any other number making that you won't append or insert again.
why are you retrieving all entries from zemployee_20 ?
You can directly check wether the 'id' exists already or not by using select single. If exists, then show message, if not, add.
It is recommended to retrieve only one field when its needed and not the entire table with asterisc *
SELECT single employee_id FROM ZEMPLOYEE_20 where employee_id = p_id INTO v_id. ( or field in structure )
if sy-subrc = 0. "exists
"show message
else. "not existing id
"populate structure and then add record to Z table
endif.
Furthermore, l_count is not only unnecessary but also bad implemented.
You can directly use the insert query,if the sy-subrc is unsuccessful raise the error message.
WA_EMP-EMPLOYEE_ID = C_ID.
WA_EMP-EMPLOYEE_NAME = C_NAME.
WA_EMP-EMPLOYEE_ADDRESS = C_ADD.
WA_EMP-EMPLOYEE_SALARY = C_SAL.
WA_EMP-EMPLOYEE_TYPE = C_TYPE.
INSERT ZEMPLOYEE_20 FROM WA_EMP.
If sy-subrc <> 0.
Raise the Exception.
Endif.

Trigger warning: created with compilation errors

i have this trigger and it says Warning: Trigger created with compilation errors.
can you give me quick advice?
/
CREATE OR REPLACE TRIGGER type_check
BEFORE INSERT ON carrs
FOR EACH ROW
BEGIN
IF :new.weight > 3500
THEN
:new.type := 'nakladne';
ELSE
:new.type := 'osobne';
END IF;
END;
/
edit: i still got the same warning
edit: here is table definition
create table carrs (
id_Car Integer not null,
id_board_unit Integer not null,
id_evc_numbers Integer not null,
id_owner Integer,
weight Integer not null );
here are the errors:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00049: bad bind variable 'NEW.TYPE'
6/5 PLS-00049: bad bind variable 'NEW.TYPE'
If you're using SQL*Plus, type show errors after getting that warning to display the list of syntax errors that were reported. It's far easier to diagnose problems when you know what they are rather than guessing.
At a minimum, your references to the :new pseudorecord need to include the colon prefix :new rather than new. The assignment operator in PL/SQL is also := not =. So, at a minimum, you'd want something like
CREATE OR REPLACE TRIGGER type_check
BEFORE INSERT ON carrs
FOR EACH ROW
BEGIN
IF :new.weight > 3500
THEN
:new.type := 'nakladne';
ELSE
:new.type := 'osobne';
END IF;
END;
There may be additional errors as well. If there are, type show errors and edit your question to include them.
If you wish to add a new column named type to your table, you would do that before creating your trigger. That's not a particularly good name for a column, though, since type is also a reserved word in Oracle. I'd choose something more meaningful like, say, carr_type. You'd have to specify how large the strings the new column would need to hold when creating it. I'll guess that you want space for 10 characters
ALTER TABLE carrs
ADD( carr_type VARCHAR2(10 CHAR) );
You then probably want to UPDATE your table to populate the new column for your existing data
UPDATE carrs
SET carr_type = (case when weight > 3500
then 'nakladne'
else 'osobne'
end)
before creating your trigger
CREATE OR REPLACE TRIGGER type_check
BEFORE INSERT ON carrs
FOR EACH ROW
BEGIN
IF :new.weight > 3500
THEN
:new.carr_type := 'nakladne';
ELSE
:new.carr_type := 'osobne';
END IF;
END;

Oracle Stored Procedure "Encountered the symbol... " error

After a looong research i have decided i have no idea what causes the following problem! I want to create a stored procedure that will increase the value of a column if that satisfied a statement.I can run the procedure as a anonymous block but i cant run it as a stored procedure!
Here is the stored procedure code:
1 create or replace
2 Procedure RaiseSalary
3 Is
4 Salary number;
5 Cursor RaiseCursor
6 Is
7 Select Salary_A From Person Where Salary_A<400 for update of Salary_A;
8 Begin
9 Open RaiseCursor;
10 Loop
11 Fetch RaiseCursor Into Salary;
12 Exit When RaiseCursor%Notfound;
13 Update Person Set Salary_A=(Salary + 200) Where Current Of RaiseCursor;
14 End Loop;
15 Close RaiseCursor;
16 Commit;
17 End;
I am getting an error at line 3 that says "Encountered the symbol "SALARY" when expecting one of the following:...." and i am getting the same error at line 5 at the "s" letter of the word Cursor ,but at this time it says ";" instead of "Salary". The compiler log shows "insufficient privileges" but i can't find a reasonable explanation for this.
I have tried to run the code as an anonymous block like this:
Declare
Salary number;
Cursor RaiseCursor
Is
Select Salary_A From Person Where Salary_A<400 for update of Salary_A;
Begin
Open RaiseCursor;
Loop
Fetch RaiseCursorInto Salary ;
Exit When RaiseCursor%Notfound;
Update Person Set Salary_A =(Salary + 200) Where Current Of RaiseCursor;
End Loop;
Close RaiseCursor;
Commit;
End;
.
run;
And works great!!!I am sure that i have the privileges to write stored procedures because i have created some successfully!
Am i doing something so wrong? I can't figure out what causes the problem, if you have any suggestions i would really appreciate that:)
EDIT: For some reason my procedure got wrong Schema that's why i had that problem! I only dropped the Procedure and create it again and it fixed!!!!
Thanks for your time anyway!
Let me just point out this would be vastly more efficient if you did it as:
UPDATE Person Set Salary_A=(Salary_A + 200)
Where Salary_A<400
No cursor, no looping. It would also be a lot simpler.

Resources