I am trying to create a type with the rowid data type, but I am getting this error because of the type I am trying to use:
SQL> CREATE TYPE join_t IS OBJECT (inn rowid, out rowid );
/
Warning: Type created with compilation errors.
Even though I can create a table with rowid data type:
SQL> create table test_rowid (inn rowid,out rowid);
Table created.
Is it possible to create this type join_t above, with rowid-type attributes?
No, you can't create an object type with rowid fields. If you looks at the actual error raised, via the user_errors view or with the SQL*Plus command show errors, you will see:
LINE/COL ERROR
-------- ------------------------------------------------------------------------------
1/28 PLS-00530: Illegal type used for object type attribute: 'ROWID'.
1/39 PLS-00530: Illegal type used for object type attribute: 'ROWID'.
The documenation says:
Restrictions on datatype
You cannot impose the NOT NULL constraint on an attribute.
You cannot specify attributes of type ROWID, LONG, or LONG RAW.
You cannot specify a data type of UROWID for an ADT.
...
As a workaround, you could potentially use a string type in your object, and convert the values when setting to getting the field values, via the rowidtochar and chartorowid functions:
CREATE TYPE join_t IS OBJECT (inn varchar2(18), out varchar2(18) );
/
Type JOIN_T compiled
SELECT join_t(rowidtochar(rowid), rowidtochar(rowid)) FROM DUAL;
JOIN_T(ROWIDTOCHAR(ROWID),ROWIDTOCHAR(ROWID))(INN, OUT)
-------------------------------------------------------
JOIN_T('AAAAB0AABAAAAOhAAA', 'AAAAB0AABAAAAOhAAA')
Storing rowids in an object doesn't seem particularly useful though, as they can change.
Related
Is it possible to access an existing table from an object?
Here the simplified snippet:
CREATE OR REPLACE TYPE MYOBJ AS OBJECT(
MEMBER PROCEDURE MYEXPORT( ERRORS.ERRORS_ID%TYPE));
ERRORS is a table. When I write it like above I'm getting error:
PLS-00201 - identifier must be declared.
Any clue? Thanks!
You have three issues:
The syntax is
MEMBER PROCEDURE procedure_name (argument_name data_type)
You have specified the data type but not an argument name which is why you get the error message PLS-00201 - identifier must be declared. as you need to specify an identifier for the argument.
table_name.column_name%TYPE declarations can be used in the PL/SQL scope but not in the SQL scope. Your object declaration is in the SQL scope so you need to fully define the data type rather than referring to a column.
An object must have at least one attribute.
You want:
CREATE OR REPLACE TYPE MYOBJ AS OBJECT(
attr1 NUMBER,
MEMBER PROCEDURE MYEXPORT( v_errors_id NUMBER )
);
I am trying to create a table with a column of object type and tricky nested table hierarchy. Getting ORA-22913 error. In CREATE table statement the column "theCol" is of type object (i.e. MainObj). MainObj contains an attribute of type nested table i.e. ChildTab.
I think am supposed to use NESTED TABLE clause in CREATE TABLE statement. But not sure how to use it here because "theCol" is NOT of nested table type.
DROP TYPE MainObj;
DROP TYPE ChildTab;
DROP TYPE ChildObj;
CREATE TYPE ChildObj AS OBJECT (
naame varchar2(20)
, kaam varchar2(20)
);
/
CREATE TYPE ChildTab AS TABLE OF ChildObj;
/
Create TYPE MainObj as OBJECT (
KEEY VARCHAR2(5),
ChildList ChildTab
);
/
CREATE TABLE TestTableDesi (
theCol MainObj
);
/
Type dropped.
Type dropped.
Type dropped.
Type created.
Type created.
Type created.
ORA-22913: must specify table name for nested table column or attribute
Just found the solution here. How do I create an Oracle table of objects containing nested tables?
The create table statement should be as follows.
CREATE TABLE TestTableDesi (
theCol MainObj
) nested table theCol.ChildList store as ChildList_tab ;
/
In oracle database I have created type
CREATE OR REPLACE TYPE DOSSIER_RESULT AS OBJECT
(
id number,
user_id number
)
Then I created the collection of this type
CREATE OR REPLACE TYPE DOSSIER_RESULTS_ARRAY AS TABLE OF DOSSIER_RESULT
Then I added one more attribute in first type definition like this
CREATE OR REPLACE TYPE DOSSIER_RESULT AS OBJECT
(
id number,
user_id number,
child DOSSIER_RESULTS_ARRAY
)
But it compiled with error
Error: PLS-00201: identifier 'DOSSIER_RESULTS_ARRAY' must be declared
The question is: How can I create an Object type with collection of objects of this type in it?
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 have a somewhat complex structure as follows :
create or replace type user_typ as object(
user_id number(19,0),
username nvarchar2(40 char)
);
I inherit an applicant_typ from this :
create or replace type applicant_typ under user_typ (
resume_text nclob
);
My design involves jobs to which applicants can apply. To this end, I create an application_typ as follows :
create or replace TYPE Application_typ AS OBJECT (
application_id NUMBER,
candidate applicant_typ,
time_of_app DATE
);
CREATE TYPE Application_tab IS TABLE OF Application_typ;
And now I want to create an object type called Job_typ, and a table containing those objects, wherein there will be a nested table for applications :
CREATE OR REPLACE TYPE Job_typ AS OBJECT (
job_ID NUMBER,
company_ID NUMBER,
description NVARCHAR2(1000),
name NVARCHAR2(200),
application Application_tab,
MAP MEMBER FUNCTION job_no RETURN NUMBER,
MEMBER PROCEDURE no_of_applicants
);
All of this works fine. The issue is when I try to create a table of type Job_typ :
CREATE TABLE Job_tab OF Job_typ
NESTED TABLE application STORE AS application_nt;
This doesn't work, giving the error :
SQL Error: ORA-02320: failure in creating storage table for nested table column APPLICATION
ORA-22913: must specify table name for nested table column or attribute
02320. 00000 - "failure in creating storage table for nested table column %s"
*Cause: An error occurred while creating the storage table for the
specified nested table column.
What am I doing wrong?
EDIT : I tried some different things. If I change application_typ as follows :
CREATE OR REPLACE TYPE Application_typ AS OBJECT (
application_id NUMBER,
candidate User_Typ, -- NOTE: This attribute is now of type User_typ instead of the inherited type
time_of_app DATE,
);
CREATE TYPE Application_tab IS TABLE OF Application_typ;
Then everything else works, and I am able to create the Job table. Why do I get the error on using the inherited type?
I tried the following in Oracle 11.2.0.1 and didn't get any error. I made a slight change though:
CREATE OR REPLACE TYPE user_typ AS OBJECT
(
user_id NUMBER (19, 0),
username NVARCHAR2 (40 CHAR)
) NOT FINAL; -- << Notice the NOT FINAL keyword
create or replace type applicant_typ under user_typ (
resume_text nclob
);
CREATE OR REPLACE TYPE Application_typ AS OBJECT
(
application_id NUMBER,
candidate applicant_typ,
time_of_app DATE
);
CREATE TYPE Application_tab IS TABLE OF Application_typ;
CREATE OR REPLACE TYPE Job_typ AS OBJECT
(
job_ID NUMBER,
company_ID NUMBER,
description NVARCHAR2 (1000),
name NVARCHAR2 (200),
application Application_tab,
MAP MEMBER FUNCTION job_no
RETURN NUMBER,
MEMBER PROCEDURE no_of_applicants
);
CREATE TABLE Job_tab OF Job_typ
NESTED TABLE application
STORE AS application_nt;
While trying to create all your types and keywords, I got the error:
[Error] PLS-00590 (10.1): PLS-00590: attempting to create a subtype UNDER a FINAL type
This is because Oracle doesn't allow creation of a subtype on a FINAL type. If you don't define any finalizing clause for the base type, the default is FINAL.
Read more on Oracle Docs.
If you are coding for the real world (read industry), I'd advise against using nested tables as column types. You end up spending your entire life trying to nest and un-nest these. I'd suggest you normalize your schema as much as you can or need and leave nested tables for operations in PL/SQL code blocks.