When creating a type of object, is it possible to declare the type as TABLE.COLUMNNAME%TYPE?
e.g.
CREATE OR REPLACE TYPE PROJECT_TYPE IS OBJECT
(
project_id project.project_id%TYPE,
project_desc project.project_desc%TYPE
);
or I have to specify the type and width at the time of creation? Reason why this question is if table is altered then I have to change to data type and width of type OBJECT as well?
It is, unfortunately, not possible. You have to provide actual type, you can not reference a %TYPE of a table's column.
The reason for that is that both %TYPE and %ROWTYPE are PL/SQL constructs, which are not supported in SQL.
Related
I have a table like this:
CREATE TABLE T_C_EVO_GAME_CONFIG_CHANGE_LOG(
F_TABLE_MODIFIED VARCHAR2(40),
F_OPERATION_PERFORMED VARCHAR2(30),
F_ROWS_ALTERED INTEGER,
F_LAST_UPDATED_BY VARCHAR2(200),
F_LAST_UPDATED_DATE TIMESTAMP);
I am trying to build a type with the same structure:
create or replace type TYPE_EVOL_CONFIG_CHANGE_LOG as object
(
F_TABLE_MODIFIED T_C_EVO_GAME_CONFIG_CHANGE_LOG.TABLE_MODIFIED%TYPE ,
F_OPERATION_PERFORMED T_C_EVO_GAME_CONFIG_CHANGE_LOG.OPERATION_PERFORMED%TYPE,
F_ROWS_ALTERED T_C_EVO_GAME_CONFIG_CHANGE_LOG.ROWS_ALTERED%TYPE ,
F_LAST_UPDATED_BY T_C_EVO_GAME_CONFIG_CHANGE_LOG.LAST_UPDATED_BY%TYPE ,
F_LAST_UPDATED_DATE T_C_EVO_GAME_CONFIG_CHANGE_LOG.LAST_UPDATED_DATE%TYPE
);
Getting the below error message in creating the Type :
Error(3,25): PLS-00201: identifier 'T_C_EVO_GAME_CONFIG_CHANGE_LOG.TABLE_MODIFIED' must be declared.
Previously I tried to create the Type without using %TYPE and just simply copying the parameter definition and it worked.
But I don't want to make any changes in Type when I make any changes in Table.
The %TYPE syntax is for use in PL/SQL declarations. Unfortunately we cannot use it when creating SQL objects. Same goes for %rowtype.
It would be highly neat if we could, because one common use of create or replace type would be to build table APIs as you want to do. However, it would be too complicated to manage referencing constructs in the data dictionary; bear in mind that Types can be used to define other objects including Table columns.
So alas, you need to declare the Type with explicit datatypes for its attributes:
create or replace type TYPE_EVOL_CONFIG_CHANGE_LOG as object
(
F_TABLE_MODIFIED VARCHAR2(40) ,
F_OPERATION_PERFORMED VARCHAR2(30),
F_ROWS_ALTERED INTEGER ,
F_LAST_UPDATED_BY VARCHAR2(20) ,
F_LAST_UPDATED_DATE DATE
);
Obviously you also need to sync it manually whenever the structure of any T_C_EVO_GAME_CONFIG_CHANGE_LOG column changes. But you would have to do this anyway if you added or dropped a column.
Alternatively you can define the type as a PL/SQL record in a package. That would allow you to use the referencing syntax.
create or replace package game_config as
TYPE_EVOL_CONFIG_CHANGE_LOG is record
(
F_TABLE_MODIFIED T_C_EVO_GAME_CONFIG_CHANGE_LOG.F_TABLE_MODIFIED%TYPE ,
F_OPERATION_PERFORMED T_C_EVO_GAME_CONFIG_CHANGE_LOG.F_OPERATION_PERFORMED%TYPE,
F_ROWS_ALTERED T_C_EVO_GAME_CONFIG_CHANGE_LOG.F_ROWS_ALTERED%TYPE ,
F_LAST_UPDATED_BY T_C_EVO_GAME_CONFIG_CHANGE_LOG.F_LAST_UPDATED_BY%TYPE ,
F_LAST_UPDATED_DATE T_C_EVO_GAME_CONFIG_CHANGE_LOG.F_LAST_UPDATED_DATE%TYPE
);
-- or even
TYPE TAB_EVOL_CONFIG_CHANGE_LOG is table of T_C_EVO_GAME_CONFIG_CHANGE_LOG%rowtype;
end;
It depends how you want to use the Type in your broader application.
I was trying to explore Oracle Collection and Record type. How do they work ? I wrote below script, but unable to compile them. What is wrong here ?
create or replace package pkg is
type ty_rec is record(empno emp.empno%type,ename emp.ename%type,sal emp.sal%type);
end pkg;
/
create or replace package body pkg is
end pkg;
/
create or replace type ty_varray is varray(5) of pkg.ty_rec;
/
create or replace type ty_table is table of pkg.ty_rec;
/
create table tab1(
id number,
col_arr ty_varray,
col_tab ty_table
) nested table col_tab store as tab1_col_tab;
/
Also, anyone could explain the Nested Table vs Varray when we are using them in table column. How do they stores data and which one is faster ?
Note: I'm using scott schema, which has default emp table
Records are a PL/SQL construct. This means they cannot be used in pure SQL statements. So you need to create the "record" type as a pure SQL object:
create or replace type ty_emp_rec as object
(empno number
,ename varchar2(20)
,sal number);
/
create or replace type ty_emp_varray is varray(5) of ty_emp_rec;
/
create or replace type ty_emp_table is table of ty_emp_rec;
/
I agree it would be highly neat if your code worked, not least because the ability to define attributes using the %TYPE syntax would be extremely useful. But alas that's restricted to the PL/SQL engine too.
This limitation is down to the ability to declare heap table columns with user-defined types, as your last example shows. Oracle requires its columns to be strongly-typed. The %TYPE syntax would create all sorts of problems here: consider what would happen if emp.empno changed from NUMBER to VARCHAR2, or vice versa.
i want to retrieve type of elements varray stores through type attribute or ANY work around.
for example our type is defined like this
CREATE TYPE "READINGS" AS VARRAY (200) OF NUMBER(21, 6);
(readings is varray with elements of type number(21,6))
READINGS is a column in a table INTERVALS. INTERVALS is a central table and we have batch processes on INTERVALS which execute sql store procedures. In store procedure we have hard coded variable declarations mapping to the READING VArray type element type which is NUMBER(21, 6) for example the store procedure has variable declarations like
CONSUMPTION NUMBER(21, 6);
whenever Varray definition is changed or varray is dropped and recreated with different size and precision, ex instead on number(21,6) is changed to number(25,9) we need to change our variable declarations in all batch process store procedures.
All i am looking for is making CONSUMPTION variable declaration, refer to element type of VArray. I want something like this
CONSUMPTION INTERVALS.READINGS.COLUMN_TYPE%TYPE;
(i want some thing like this, refer to the type of elements stored by varray)
Why are you creating a table with a VARRAY column in the first place? It would generally make far more sense to create a separate table for READINGS with a foreign key that lets you relate the rows back to the INTERVALS table. You could then easily enough declare columns of type READINGS.COLUMN_NAME%TYPE.
Collections are wildly useful in PL/SQL. I've never seen a case where they improved on a standard normalized approach to data modeling. I have seen multiple cases where incorporating collections into your data model ends up making your data model harder to work with and your code harder to write and maintain.
If you don't want to fix the data model, you can
Declare a SUBTYPE or a packaged variable of type NUMBER(21, 6) that you use as the type for your variable declarations. You'll have to change this definition if and when you change the declaration of the VARRAY type.
Create an object type with a single attribute (a NUMBER(21,6)) and define the VARRAY based on that object type. Then you can declare instances of the object type in your code.
This is not a required solution, but you can get string of type definition for further using it in dynamic SQL
SELECT
regexp_substr(text, 'VARRAY.*?OF\s+(.+?)(;|\s)*$', 1, 1, 'i', 1)
FROM user_source
WHERE name = 'READINGS'
I'm newbee in oracle and
I try to change varchar(50) to 250
CREATE OR REPLACE TYPE CEQ_OWNER.TYPE_REC_PARAE2
AS OBJECT
(
...
BONETAT_DESC VARCHAR2(250),
...
)
/
I get ORA-02303: cannot drop or replace a type with type or table dependents
There are other types or tables that depend on the type you want to change. If it's a dependent type, then you can use the FORCE option to change the type.
If it's a table that directly or indirectly uses the type, then you will need to create a new type and a new table, migrate all the data, and finally drop and rename tables and types.
See this Oracle documentation for some further information.
I was looking everywhere for the syntax also, but was having a hard time finding the documentation. From the page that Codo linked... notice that the FORCE is between the object name and as object
create or replace type ceq_owner.type_rec_parae2 FORCE as object
(
...
BONETAT_DESC VARCHAR2(250),
...
)
/
Try:
drop type your_type force;
There are some dependency for the Object you are trying to Modify or Drop.
If you want to skip this first drop the dependant Object and try to DROP or MODIFY
Like in the below Screenshot
Regards,
Arul
I am new to Oracle and have just read that the scalar variable has no internal component whereas composite variable has an internal component.
Could you please explain what is this internal component?
How does it work? What is its purpose ?
You need to read the documentation about PL/SQL Records and Collections:
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/composites.htm
A composite variable's internal components are simply the structure that makes up the variable itself.
e.g.
In a collection, the internal components always have the same data
type, and are called elements. You can access each element of a
collection variable by its unique index, with this syntax:
variable_name(index). To create a collection variable, you either
define a collection type and then create a variable of that type or
use %TYPE.
In a record, the internal components can have different data types,
and are called fields. You can access each field of a record variable
by its name, with this syntax: variable_name.field_name. To create a
record variable, you either define a RECORD type and then create a
variable of that type or use %ROWTYPE or %TYPE.
For example, if I create a record type:
TYPE person_rectype IS RECORD (
forename VARCHAR2(30),
surname VARCHAR2(30),
sex VARCHAR2(1),
dob DATE
);
then declare a variable of that type:
applicant_rec person_rectype;
The variable applicant_rec has the internal components forename, surname, sex and dob which are VARCHAR2 and DATE data types.
Hope it helps...