How to fetch data in nested record in PL/SQL? - plsql

I was trying to work on nested record example.
Please have a look at declaration section.
DECLARE
TYPE r_emp IS RECORD (
name VARCHAR2(50),
dept_rec departments%ROWTYPE
);
r_emp_row r_emp;
BEGIN
SELECT emp.first_name||' '||emp.last_name,dept.*
INTO r_emp_row
FROM employees emp,departments dept
WHERE emp.department_id = dept.department_id
AND emp.employee_id = 100;
DBMS_OUTPUT.PUT_LINE('Name:'||r_emp_row.name);
DBMS_OUTPUT.PUT_LINE('Department ID:'||r_emp_row.dept_rec.department_id);
DBMS_OUTPUT.PUT_LINE('Department Name:'||r_emp_row.dept_rec.department_name);
EXCEPTION
when others then
null;
END;
I am trying to run above block but getting error as below:
Error report -
ORA-06550: line 10, column 8:
PLS-00597: expression 'R_EMP_ROW' in the INTO list is of wrong type
ORA-06550: line 11, column 3:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 9, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
Help appreciated.

Your record type r_emp is a composite of one scalar attribute and one record, so you will need to reflect that in the select into. Something like:
select emp.first_name||' '||emp.last_name, dept.*
into r_emp_row.name, r_emp_row.deptrec.dempno, r_emp_row.deptrec.dname ...
btw unrelated to the problem, when others then null is a famously dangerous construction:
What is bad in "When Others Then Null" in PL/SQL?
http://www.orafaq.com/wiki/WHEN_OTHERS
http://tkyte.blogspot.co.uk/2008/06/when-others-then-null-redux.html
What if there is no employee 100? Fine, it does nothing - perhaps that's OK. What if there is an employee 100 but there is a corrupt block in the index causing the query to fail with ORA-01578: ORACLE data block corrupted, or not, depending on the execution plan? It does nothing and doesn't tell you, and you'll think there's no employee 100.

Related

Getting error while assigning values to records inside collection

I need to loop through some values inside the plsql code.
so trying to create a collection of records .
getting error as mentioned below.
Please help me to resolve
-- please see the code below
declare
type tab_name is record (t_name varchar2(30),col_name varchar2(30));
type tab_list is table of tab_name;
table_names tab_list:=tab_list(tab_name('ABC','abc'),tab_name('XYZ','xyz'));
begin
for i in table_names.first..table_names.last loop
dbms_output.put_line(table_names(i).t_name||'-'||table_names(i).col_name);
end loop;
end;
/
Error report -
ORA-06550: line 4, column 32:
PLS-00222: no function with name 'TAB_NAME' exists in this scope
ORA-06550: line 4, column 13:
PL/SQL: Item ignored
ORA-06550: line 6, column 10:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 6, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Record type's name is not its initializer.
In fact, there is no initialization-like function for record types at all in oracle:
Documentation
Note that values are assigned separately to each field of a record in
Example 5-47. You cannot assign a list of values to a record using an
assignment statement. There is no constructor-like notation for
records.
You have to create each object separately and then create collection with them:
declare
type tab_name is record (t_name varchar2(30),col_name varchar2(30));
type tab_list is table of tab_name;
name_1 tab_name;
table_names tab_list;
begin
name_1.t_name := 'ABC';
name_1.col_name := 'abc';
table_names := tab_list();
table_names.extend;
table_names(table_names.last) := name_1;
name_1.t_name := 'XYZ';
name_1.col_name := 'xyz';
table_names.extend;
table_names(table_names.last) := name_1;
for i in table_names.first..table_names.last
loop
dbms_output.put_line(table_names(i).t_name||'-'||table_names(i).col_name);
end loop;
end;
Collections DO have initializers. However, in your case you have a collection of record types, so you would have to have your records pre-created to make use of it.

PL/SQL compilation error

What is wrong with the following statement:
DECLARE
int_exists INTEGER;
BEGIN
SELECT COUNT(ItemKey)
INTO int_exists
FROM BIR_TabsForDashboard
WHERE ItemKey = 'Position';
IF( int_exists = 0 ) THEN --doesnt exist
EXECUTE IMMEDIATE 'ALTER TABLE BIR_TabsForDashboard ADD Position int NULL';
END IF;
END;
I get this report error:
ORA-06550: line 7, column 9:
PL/SQL: ORA-00904: "ITEMKEY": invalid identifier
ORA-06550: line 4, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
What could be wrong? It seems to work when I use it on another table but for some reason it comes up with this error when I do it to this specific table?
The table BIR_TabsForDashboard does not have a column named ItemKey.
Make sure the procedure which you are using is should properly declared in the place which you are using it. For an example if it is under an another user and in an another package then it should be in that same order. The username, package and procedure name.

Invalid identifier while updating a column using cursor for loop?

I am trying to update salary column in my table using cursors.
This is my code:
declare
cursor c1 is
select * from emp2_1030082;
begin
for c3 in c1
loop
if(c3.salary>10000)
then
update emp2_1030082 set c3.salary=c3.salary + c3.salary/10 ;
elsif(c3.salary<=10000)
then
update emp2_1030082 set c3.salary= c3.salary + c3.salary/20 ;
end if;
end loop;
end;
But I'm getting this error:
ORA-06550: line 9, column 47:
PL/SQL: ORA-00904: "C3"."SALARY": invalid identifier
ORA-06550: line 9, column 1:
PL/SQL: SQL Statement ignored
ORA-06550: line 12, column 25:
PL/SQL: ORA-00904: "C3"."SALARY": invalid identifier
ORA-06550: line 12, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The first question is, do you really need to do this in a cursor? Because executing these two statements should do what you want:
update emp2_1030082 set salary=salary + salary/10 where salary > 10000;
update emp2_1030082 set salary=salary + salary/20 where salary <= 10000;
Meanwhile, the error you are getting is because in
update emp2_1030082 set c3.salary=c3.salary + c3.salary/10 ;
By using the c3. in set c3.salary you are referring to the cursor instead of the column name in the table that you want to update. Just salary (and in the other update as well) should make the error go away, BUT, you will update all rows with every update, so pretty sure that's not what you want.
To do it with a cursor, you should remove the the c3. from where it doesn't belong, and then add a where clause to update only the current record. Hopefully you have some kind of unique ID, and then it would be something like:
update emp2_1030082 set salary=c3.salary + c3.salary/10 where id = c3.id;

Simple PL/SQL function to test if a string is a number

I'm experienced with T-SQL from SQL Server, but have recently begun working on a project utilizing an Oracle database (11g) and am having some issues writing what seems to be basic code.
I need to test whether a set of values are numeric, and only insert them into a table if they are. PL/SQL doesn't seem to have an is_number function, so I wrote my own based on an AskTom question.
create or replace
function IS_NUMBER(str in varchar2) return boolean
IS
n number;
BEGIN
select to_number(str) into n from dual;
return (true);
EXCEPTION WHEN OTHERS THEN
return (false);
END;
Eventually, I'd like to use this function in a WHERE clause, but for now I'm just trying to get it to run at all:
declare
str varchar2(1);
n boolean;
begin
str := '0';
select ca_stage.is_number(str) into n from dual;
end;
In SQL Developer, trying to run this gives me the following error report:
Error report:
ORA-06550: line 6, column 39:
PLS-00382: expression is of wrong type
ORA-06550: line 6, column 19:
PLS-00382: expression is of wrong type
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The error report is straight-forward, but doesn't make sense. The function accepts a varchar2, and that's what I'm using as an input variable. It returns a boolean and again, that's what I'm using.
As I said, this is basic code, so I assume that I'm missing something fundamental.
Return a SQL datatype, e.g. VARCHAR2. Also, I'd recommend against using WHEN OTHERS. Also, you don't need a query on dual:
create or replace
function IS_NUMBER(str in varchar2) return varchar2
IS
n number;
BEGIN
n := to_number(str);
return 'Y';
EXCEPTION WHEN VALUE_ERROR THEN
return 'N';
END;

Create and Insert into nested table

Please forgive me, somebody else from my class has asked this question but the answer didn't quite meet my needs. This is coursework so I do not want spoon feeding the answer but a nudge in the right direction would help. I also know that other class friends are using this forum to assist with their work so this answer would be really useful.
This is the question as it has been asked:
(a) A PL/SQL procedure called INIT_ACTOR_QUOTES with no parameters that:
i. Reads ALL the ACTORIDs from the ACTOR table and INSERTs them into the ACTORID attribute for each row the ACTOR_QUOTES table (the tables have the same cardinality) and at the same time INSERTs the following initial values into the first row only of the QUOTES nested table into each row of the ACTOR_QUOTES table;
(Movie_Title, Year, Role, Quote) are set respectively to (' ',NULL ,' ', ' ')
Also and at the same time immediately after each INSERT use DELETE to delete ALL the rows from the nested table in each row belonging to each ACTORID in the ACTOR_QUOTES table. (NB: this may seem strange but is necessary as the nested table cannot be populated (because it is atomically null) unless it is initialized, after which this initial data may be deleted).
This is what I have come up with and the response that I get:
CREATE OR REPLACE PROCEDURE INIT_ACTOR_QUOTES
AS
CURSOR actorID_cursor IS
SELECT actorID FROM Actor;
BEGIN
FOR row IN actorID_cursor LOOP
INSERT INTO actor VALUES (
'00001',
actor_quotes_NT (
quote ('', NULL, ' ', '')
);
DELETE (*) FROM Quotes_NT ('', NULL, ' ', '');
END LOOP;
END INIT_ACTOR_QUOTES ;
/
LINE/COL ERROR
-------- -----------------------------------------------------------------
8/1 PL/SQL: SQL Statement ignored
13/2 PL/SQL: ORA-00917: missing comma
16/1 PL/SQL: SQL Statement ignored
16/9 PL/SQL: ORA-00928: missing SELECT keyword
20/1 PLS-00103: Encountered the symbol "/"
I sort of get the principle of what my lecturer is asking but this is giving me a blooming headache. Please help.
Do you need any more information?

Resources