I've created a sample oracle function to returns the number of records in a table. Here is it
create or replace FUNCTION TEST_COUNT
RETURN NUMBER AS recCount NUMBER;
BEGIN
SELECT COUNT(*) INTO recCount FROM **tableName**;
return recCount;
END TEST_COUNT;
Its' being compiled successfully, but when I called this function in Oracle SQL-Developr using command
SELECT * FROM TABLE (TEST_COUNT());
it threw me the following error.
ORA-22905: cannot access rows from a non-nested table item
22905. 00000 - "cannot access rows from a non-nested table item"
*Cause: attempt to access rows of an item whose type is not known at
parse time or that is not of a nested table type
*Action: use CAST to cast the item to a nested table type
Error at Line: 1 Column: 22
I've followed Oracle error ORA-22905: cannot access rows from a non-nested table item but can't reach the solution. Please suggest what should I do?
Well, you're just calling it wrong. The TABLE() table collection expression is used when the function returns a collection (e.g. from create type x as table of number) that you want to treat as a table so you can join against it, which isn't the case here; you're returning a simple NUMBER.
So just do:
SELECT TEST_COUNT FROM DUAL;
Related
I need to get the year from a date in all of the records in an Oracle database. The following is my attempt:
CREATE or replace TYPE BODY student_t AS MEMBER FUNCTION getYear RETURN NUMBER IS
yearDOB NUMBER;
BEGIN
SELECT EXTRACT(YEAR FROM s.dob) INTO yearDOB
from student s;
return yearDOB;
END;END;/
But that will not work when the table has more than 1 record.
How I can fix the issue?
When you do select into rdbms thinks that only one value will be returned, or that your variable will be an array. You cannot set a NUMBER variable to an array of objects.
As the title said : I want to create a type in oracle based on an existing Table.
I did as follow :
create or replace type MY_NEW_TYPE as object( one_row EXISTING_TABLE%rowtype);
The Aim is to be able to use this into a function which will return a table containing sample row of the table EXISTING_TABLE :
create or replace function OUTPUT_FCT() return MY_NEW_TYPE AS
...
If you only need to create a function that returns a row from your table, you could try something like the following, without creating types.
setup:
create table EXISTING_TABLE( a number, b varchar2(100));
insert into EXISTING_TABLE values (1, 'one');
function:
create or replace function OUTPUT_FCT return EXISTING_TABLE%rowtype AS
retVal EXISTING_TABLE%rowType;
begin
select *
into retVal
from EXISTING_TABLE
where rownum = 1;
--
return retVal;
end;
function call
SQL> begin
2 dbms_output.put_line(OUTPUT_FCT().a);
3 dbms_output.put_line(OUTPUT_FCT().b);
4 end;
5 /
1
one
However, I would not recommend such an approach, because things like select * can be really dangerous; I would much prefer defining a type with the fields I need, and then explicitly query my table for the needed columns.
No, you can't do that, you'll get a compilation error:
create or replace type my_new_type as object(one_row t42%rowtype);
/
Type MY_NEW_TYPE compiled
Errors: check compiler log
show errors
Errors for TYPE STACKOVERFLOW.MY_NEW_TYPE:
LINE/COL ERROR
-------- -----------------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
1/36 PLS-00329: schema-level type has illegal reference to MYSCHEMA.T42
You will need to specify each field in the object type, and you will have to specify the data types manually too - you can't use table.column%type either.
You could create the type dynamically based on column and data type information from the data dictionary, but as this will (hopefully) be a one-off task and not something you'd do at runtime, that doesn't really seem worth it.
You can create a PL/SQL table type based on your table's rowtype, but you would only be able to call a function returning that from PL/SQL, not from plain SQL - so you couldn't use it in a table collection expression for example. If you were only returning a single sample row you could return a record rather than a table, but the same applies. You can also have a function that returns a ref cursor which could match the table's structure, but you wouldn't be able to treat that as a table either.
Read more about object type creation in the documentation. Specifically the attribute and datatype sections.
I'm trying to create some output based on select items from APEX.
The case is as follows:
In APEX you select certain items.
APEX makes a nested table of those primary keys and call the function to create the output.
The function generates the output and returns it.
I already found out that I can't use locally defined nested tables in the where clause, but I am now stuck on the following:
My stored type:
CREATE OR REPLACE EDITIONABLE TYPE "T_NUMBERS" as table of NUMBER(10,0)
The part of the function that gives the ORA-06550 error:
DECLARE
c_asked T_NUMBERS;
BEGIN
c_asked := T_NUMBERS(21);
This is just a simple example of what is going wrong.
The error itself:
ORA-06550: line 9, column 23:
PL/SQL: ORA-00932: inconsistent datatypes: expected NUMBER got <schema_name>.T_NUMBERS
I have a table that has one of its columns as a nested table.
I want to copy data of this table to another. How do we frame the INSERT clause for this seems challenging:
Consider. The field that is a nested table is phone_list whose type is a user defined type "TBL_PHONE_EXTN" which is a table of "typ_phone_extn".
CREATE OR REPLACE TYPE typ_phone_extn AS OBJECT
(phone_number VARCHAR2 (20), extension VARCHAR2 (10));
/
CREATE OR REPLACE TYPE tbl_phone_extn AS TABLE OF typ_phone_extn;
/
Obviously below fails: (with a ORA-00904: : invalid identifier)
INSERT INTO sch2.sub_pat_address (
pat_address_id,
pat_id,
**phone_list,**
last_updated_by
)
SELECT pat_address_id,
pat_id,
**phone_list,**
last_updated_by
FROM sch1.sub_pat_address ;
So i try:
SELECT pat_address_id,
pat_id,
**tbl_phone_extn(typ_phone_extn (phone_number,extension)),**
last_updated_by
FROM sch1.sub_pat_address, **table(phone_list)** ;
What this does is unnest the nested table. So i end up with more records than i want - meaning if a specific pat_address_id had a phone_list of 5 phone,extn combination this gives me 5 records that i cannot and should not be inserting.
So question is, how to keep the nest (nested table column) as-is and insert into the new table? Well, CTAS may be one option but that requires a whole new table instead of a INSERT. Any help will be greatly appreciated.
You can use the COLLECT function to reassemble the unnested elements into a nested table, casting that back to your actual collection type:
SELECT pat_address_id,
pat_id,
cast(collect(typ_phone_extn(phone_number,extension)) as tbl_phone_extn),
last_updated_by
FROM sch1.sub_pat_address, table(phone_list)
GROUP BY pat_address_id, pat_id, last_updated_by;
And you can then use that for your insert, obviously.
The only reason I can see you'd have a problem with your original simple insert would be if each schema had its own types and their tables were built using their own types. But then you'd get ORA-00932: inconsistent datatypes or ORA-01031: insufficient privileges rather than ORA-00904.
Even if you have privileges on the types across the schemas, Oracle UDTs have to be the exact same type - it's not enough for them to be constructed identically. If they are different entries in ALL_OBJECTS then they are not interchangeable.
In an Oracle package I have defined a type
type setTable is table of my_sets.pkey%type;
in the package declaration (the non-body part). The pkey column referenced is a number(38). Then in a function in the package body I have
...
with d as (select column_value from table(sets)),
...
where sets is a parameter to the function of type settable. This line fails to compile with the error 'ORA-22905: cannot access rows from a non-nested table item'. What can I do to resolve this?
The select statement is SQL not PL/SQL, and the SQL engine can only work with types defined on the server like this:
create type setObj is object (<attributes>);
create type setTable is table of setObj;