I want to create a type with an attribute which should be expect three possible values. Something like following statement:
CREATE TYPE my_type AS OBJECT(
attrib1 VARCHAR2(30),
attrib2 VARCHAR2(30),
attrib3 VARCHAR2(30) -- this attribute should accept three possible values: val1, val2, or val3
);
Is there any way to do this, just like in the case of tables?
Thank you in advance.
You may use custom type constructor and perform this check inside PL/SQL code.
create type my_type as object(
attrib1 varchar2(30),
attrib2 varchar2(30),
attrib3 varchar2(30),
constructor function my_type (
attrib1 in varchar2,
attrib2 in varchar2,
attrib3 in varchar2
) return self as result
);
/
create type body my_type as
constructor function my_type (
attrib1 in varchar2,
attrib2 in varchar2,
attrib3 in varchar2
) return self as result
as
invalid_attr_value exception;
pragma exception_init(invalid_attr_value, -20001);
begin
if attrib3 not in ('val1', 'val2', 'val3') then
raise_application_error(-20001, 'Invalid attrib3 value supplied');
end if;
self.attrib1 := attrib1;
self.attrib2 := attrib2;
self.attrib3 := attrib3;
return;
end;
end;/
with a(col) as (
select my_type('a', 'b', 'val1')
from dual
)
select
a.col.attrib1,
a.col.attrib2,
a.col.attrib3
from a a
COL.ATTRIB1
COL.ATTRIB2
COL.ATTRIB3
a
b
val1
with a(col) as (
select my_type('a', 'b', 'val10')
from dual
)
select
a.col.attrib1,
a.col.attrib2,
a.col.attrib3
from a a
ORA-20001: Invalid attrib3 value supplied
ORA-06512: at "FIDDLE_INSFSVTZEJFLABZQAKDJ.MY_TYPE", line 12
fiddle
This is what you'd be happy with, but - unfortunately - it won't work:
SQL> create or replace type my_type as object
2 (attrib1 varchar2(30),
3 attrib2 varchar2(30),
4 attrib3 varchar2(30) check(attrib3 in ('A', 'B'))
5 );
6 /
create or replace type my_type as object
*
ERROR at line 1:
ORA-06545: PL/SQL: compilation error - compilation aborted
ORA-06550: line 4, column 23:
PLS-00103: Encountered the symbol "CHECK" when expecting one of the following:
:= ) , not null default external character
The symbol ":= was inserted before "CHECK" to continue.
ORA-06550: line 0, column 0:
PLS-00565: MY_TYPE must be completed as a potential REF target (object type)
Therefore, create the type as is ...
SQL> create or replace type my_type as object
2 (attrib1 varchar2(30),
3 attrib2 varchar2(30),
4 attrib3 varchar2(30)
5 );
6 /
Type created.
... and then apply check constraint on attrib3 while using that type in create table statement, e.g.
SQL> create table test of my_type
2 (attrib1 primary key,
3 attrib2 not null,
4 attrib3 default 'A' check (attrib3 in ('A', 'B'))
5 );
Table created.
SQL>
Is there any way to do this, just like in the case of tables?
No, you cannot apply a CHECK constraint to an OBJECT data-type.
From the CONSTRAINT documentation:
Constraint clauses can appear in the following statements:
CREATE TABLE (see CREATE TABLE)
ALTER TABLE (see ALTER TABLE)
CREATE VIEW (see CREATE VIEW)
ALTER VIEW (see ALTER VIEW)
So you cannot create a constraint in a CREATE TYPE or an ALTER TYPE statement.
i am trying to create a procedure to add a new sale, but for some reason i am getting an error that says the column not allowed here
Here is the code:
CREATE OR REPLACE PROCEDURE AddSale
(
In_CID customers.CID%Type,
In_EmpID Employees.EmpID%Type,
In_car_num cars.car_num%Type,
In_Pay_M Sales.Pay_method%Type,
In_Payment_duration Sales.Pay_duration%Type,
In_Payment_type Sales.S_type%Type,
In_sh_id Sales.sh_id%Type,
)
IS
number := 0;
Id_sale number;
BEGIN
INSERT INTO Sales(Sales_ID, CID, EmpID, car_num, S_time,
S_type, Pay_method, Pay_duration, sh_id)
VALUES (Sales_ID_Seq.nextval, In_CID, In_EmpID, In_car_num, SYSDATE,
In_Payment_type, In_Payment_M, In_Payment_duration, In_sh_id);
And here is the table definition:
create table Sales
(
Pay_duration number(15),
Car_num number(15),
Sales_ID number(15),
S_type varchar2(15),
CID number(15),
Pay_method varchar2(32),
S_time timestamp,
EmpID number(15),
Sh_id number(15),
discount number(5,3),
Disc_status varchar2(20),
ApprovedBy number(15)
);
I've formatted the code in your request. You will see that proper formatting is a great help when coding.
In your declaration you have:
In_Pay_M
In your insert statement you have:
In_Payment_M
Then, there is a comma too many after your last parameter:
In_sh_id Sales.sh_id%Type,
)
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have the following small function that does not compile:
CREATE OR REPLACE PROCEDURE insertarVentas(ID NUMBER, IDCliente NUMBER, nombre VARCHAR2, calle VARCHAR2, poblacion VARCHAR2, cp NUMBER, provincia VARCHAR2, dni VARCHAR2,
telef1 VARCHAR2, telef2 VARCHAR2, telef3 VARCHAR2, fechaventa date, numerolinea NUMBER, IDProducto NUMBER, descripcion VARCHAR2, pvp NUMBER, stockactual NUMBER, cantidad NUMBER) AS
BEGIN
INSERT INTO TABLA_VENTAS VALUES (ID, TIP_CLIENTE(IDCliente, nombre, TIP_DIRECCION(calle, poblacion, cp, provincia), dni, TIP_TELEFONOS(telef1, telef2, telef3)), fechaventa,
TIP_LINEAS_VENTA(numerolinea, TIP_PRODUCTO(IDProducto, descripcion, pvp, stockactual), cantidad));
END insertarVentas;
The compiler gives me the following errors:
Error at line 4: PL/SQL: SQL Statement ignored
2. telef1 VARCHAR2, telef2 VARCHAR2, telef3 VARCHAR2, fechaventa date, numerolinea NUMBER, IDProducto NUMBER, descripcion VARCHAR2, pvp NUMBER, stockactual NUMBER, cantidad NUMBER) AS
3. BEGIN
4. INSERT INTO TABLA_VENTAS VALUES (ID, TIP_CLIENTE(IDCliente, nombre, TIP_DIRECCION(calle, poblacion, cp, provincia), dni, TIP_TELEFONOS(telef1, telef2, telef3)), fechaventa,
5. TIP_LINEAS_VENTA(numerolinea, TIP_PRODUCTO(IDProducto, descripcion, pvp, stockactual), cantidad));
6. END insertarVentas;
This is an insert into a object table, this is the code that table
CREATE TABLE TABLA_VENTAS OF TIP_VENTA(
IDVENTA PRIMARY KEY
)NESTED TABLE LINEAS STORE AS TABLA_LINEAS;
CREATE TYPE TIP_VENTA AS OBJECT(
IDVENTA NUMBER,
IDCLIENTE REF TIP_CLIENTE,
CREATE TYPE TIP_CIENTE AS OBJECT(
IDCLIENTE NUMBER,
NOMBRE VARCHAR2(50),
DIREC TIP_DIRECCION,
CREATE TYPE TIP_DIRECCION AS OBJECT(
CALLE VARCHAR2(50),
POBLACION VARCHAR2(50),
CODPOSTAL NUMBER(5),
PROVINCIA VARCHAR2(40)
);
NIF VARCHAR2(9),
TELEF TIP_TELEFONOS
CREATE TYPE TIP_TELEFONOS AS VARRAY(3) OF VARCHAR2(15);
);
FECHAVENTA DATE,
LINEAS TIP_LINEAS_VENTA,
CREATE TYPE TIP_LINEAVENTA AS OBJECT(
NUMEROLINEA NUMBER,
IDPRODUCTO REF TIP_PRODUCTO,
CREATE TYPE TIP_PRODUCTO AS OBJECT(
IDPRODUCTO NUMBER,
DESCRIPCION VARCHAR2(80),
PVP NUMBER,
STOCKACTUAL NUMBER
);
CANTIDAD NUMBER
);
CREATE TYPE TIP_LINEAS_VENTA AS TABLE OF TIP_LINEAVENTA;
);
What is causing this error and how can I fix it?
The PL/SQL: SQL Statement ignored message is usually just the top of the error stack and a following line will indicate what the actual issue is.
Having untangled your object creation statements and got them in an order that lets them all compile (and fixed at least one typo, and guess that a dangling comma was also a typo), creating your procedure gets:
LINE/COL ERROR
-------- ------------------------------------
4/1 PL/SQL: SQL Statement ignored
4/13 PL/SQL: ORA-00947: not enough values
You've defined TIP_VENTA with five fields:
CREATE TYPE TIP_VENTA AS OBJECT(
IDVENTA NUMBER,
IDCLIENTE REF TIP_CLIENTE,
FECHAVENTA DATE,
LINEAS TIP_LINEAS_VENTA,
CANTIDAD NUMBER
);
But the object you create during your insert only has four values (reformatted to make it a bit more readable):
INSERT INTO TABLA_VENTAS VALUES (
ID,
TIP_CLIENTE(
IDCliente,
nombre,
TIP_DIRECCION(calle, poblacion, cp, provincia),
dni,
TIP_TELEFONOS(telef1, telef2, telef3)
),
fechaventa,
TIP_LINEAS_VENTA(
numerolinea,
TIP_PRODUCTO(IDProducto, descripcion, pvp, stockactual),
cantidad
)
);
You've got cantidad inside the TIP_LINEAS_VENTA() constructor call, instead of after it:
INSERT INTO TABLA_VENTAS VALUES (
ID,
TIP_CLIENTE(
IDCliente,
nombre,
TIP_DIRECCION(calle, poblacion, cp, provincia),
dni,
TIP_TELEFONOS(telef1, telef2, telef3)
),
fechaventa,
TIP_LINEAS_VENTA(
numerolinea,
TIP_PRODUCTO(IDProducto, descripcion, pvp, stockactual)
),
cantidad
);
But that now gets:
LINE/COL ERROR
-------- ------------------------------------------------------------------
9/1 PL/SQL: SQL Statement ignored
20/5 PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
The fourth field of the TIP_VENTA is type TIP_LINEAS_VENTA, so you need to have a TIP_LINEAVENTA within that table constructor:
TIP_LINEAS_VENTA(
TIP_LINEAVENTA(
numerolinea,
TIP_PRODUCTO(IDProducto, descripcion, pvp, stockactual)
)
Which then gets:
LINE/COL ERROR
-------- -----------------------------------------------------------------------------------------------------------------
9/1 PL/SQL: SQL Statement ignored
22/7 PL/SQL: ORA-00932: inconsistent datatypes: expected X.TIP_PRODUCTO got REF X.TIP_PRODUCTO
... because you're using actual objects instead of REFs to them, as the other type definitions expect. You'll need to decide whether to make them actual objects or fix the REFs...
I think the issue is that you're trying to insert into a table of an object something that isn't an object.
I've split out your object type populations into variables (rather than leaving them nested inside the insert statement as you did) which hopefully enables you to see what it is you're actually trying to insert:
create or replace procedure insertarventas (id number,
idcliente number,
nombre varchar2,
calle varchar2,
poblacion varchar2,
cp number,
provincia varchar2,
dni varchar2,
telef1 varchar2,
telef2 varchar2,
telef3 varchar2,
fechaventa date,
numerolinea number,
idproducto number,
descripcion varchar2,
pvp number,
stockactual number,
cantidad number)
as
v_tip_venta tip_venta;
v_tip_cliente tip_cliente;
v_tip_direccion tip_direccion;
v_tip_telefonos tip_telefonos;
v_tip_lineaventa tip_lineaventa;
v_tip_lineas_venta tip_lineas_venta;
v_tip_producto tip_producto;
begin
v_tip_direccion := tip_direccion (calle,
poblacion,
cp,
provincia);
v_tip_telefonos := tip_telefonos (telef1,
telef2,
telef3);
v_tip_cliente := tip_cliente (idcliente,
nombre,
v_tip_direccion,
dni,
v_tip_telefonos);
v_tip_producto := tip_producto (idproducto,
descripcion,
pvp,
stockactual);
v_tip_lineaventa := tip_lineaventa (numerolinea,
v_tip_producto,
cantidad);
v_tip_lineas_venta := tip_lineas_venta (v_tip_lineaventa);
-- this is the step you were missing
v_tip_venta := tip_venta (id,
v_tip_cliente,
fechaventa,
v_tip_lineas_venta);
insert into tabla_ventas
values (v_tip_venta);
end insertarventas;
/
N.B. untested.
Ok, the presence of the REFs in the object type descriptions is what is causing the problems. However, I don't think it's necessary to use REF (not to mention that I couldn't work out how to make the code work with them! *{;-) ), so here is a working test case without the REFs:
drop procedure insertarventas;
drop table tabla_ventas;
drop type tip_venta;
drop type tip_lineas_venta;
drop type tip_lineaventa;
drop type tip_producto;
drop type tip_cliente;
drop type tip_telefonos;
drop type tip_direccion;
create type tip_direccion as object (calle varchar2(50),
poblacion varchar2(50),
codpostal number(5),
provincia varchar2(40));
create type tip_telefonos as varray(3) of varchar2(15);
create type tip_cliente as object (idcliente number,
nombre varchar2(50),
direc tip_direccion,
nif varchar2(9),
telef tip_telefonos);
create type tip_producto as object (idproducto number,
descripcion varchar2(80),
pvp number,
stockactual number);
create type tip_lineaventa as object (numerolinea number,
idproducto tip_producto,
cantidad number);
create type tip_lineas_venta as table of tip_lineaventa;
create type tip_venta as object (idventa number,
idcliente tip_cliente,
fechaventa date,
lineas tip_lineas_venta);
create table tabla_ventas of tip_venta (idventa primary key)
nested table lineas store as tabla_lineas;
create or replace procedure insertarventas (id number,
idcliente number,
nombre varchar2,
calle varchar2,
poblacion varchar2,
cp number,
provincia varchar2,
dni varchar2,
telef1 varchar2,
telef2 varchar2,
telef3 varchar2,
fechaventa date,
numerolinea number,
idproducto number,
descripcion varchar2,
pvp number,
stockactual number,
cantidad number)
as
v_tip_venta tip_venta;
v_tip_cliente tip_cliente;
v_tip_direccion tip_direccion;
v_tip_telefonos tip_telefonos;
v_tip_lineaventa tip_lineaventa;
v_tip_lineas_venta tip_lineas_venta;
v_tip_producto tip_producto;
begin
v_tip_direccion := tip_direccion (calle,
poblacion,
cp,
provincia);
v_tip_telefonos := tip_telefonos (telef1,
telef2,
telef3);
v_tip_cliente := tip_cliente (idcliente,
nombre,
v_tip_direccion,
dni,
v_tip_telefonos);
v_tip_producto := tip_producto (idproducto,
descripcion,
pvp,
stockactual);
v_tip_lineaventa := tip_lineaventa (numerolinea,
v_tip_producto,
cantidad);
v_tip_lineas_venta := tip_lineas_venta (v_tip_lineaventa);
-- this is the step you were missing
v_tip_venta := tip_venta (id,
v_tip_cliente,
fechaventa,
v_tip_lineas_venta);
insert into tabla_ventas
values (v_tip_venta);
end insertarventas;
/
Thanks Friend, a little more edit.
I have data in a table type,
Oracle 11g PLSQL.
inside that table type another table type , and inside another table type
for example
header_table_type has
columns header_id (Number)
item_name (varchar2)
item_type (varchar2)
service_detail **(Service_table_type)**
service_table_type has
columns service_name (Varchar2),
service_id (varchar2)
service_details **(service_term_table_type)**
service_term_table_type has
service_1 varchar2,
service_2 varchar2 ,
service 2 varchar2.
My table_type has the structure as above mentioned . Is there any way to make this table_type into an XML format. for sending through a Web service.
Please help
Of course this is possible by using function
XMLTYPE()
Try this example
create type service_term_table_type as object (
service_1 varchar2(30),
service_2 varchar2(30),
service_3 varchar2(30)
)
/
create type service_table_type as object (
service_id varchar2(30),
service_details service_term_table_type
)
/
create type header_table_type as object (
header_id number,
item_name varchar2(30),
item_type varchar2(30),
service_detail service_table_type)
/
create table xml_example (a xmltype)
/
declare
mytype header_table_type:=header_table_type(1,'a','b',service_table_type('c',service_t erm_table_type('d','e','f')));
x xmltype;
begin
x:=xmltype(mytype);
insert into xml_example values (x);
end;
Now you can see the result:
select substr(a,1,500) from xml_example;
<HEADER_TABLE_TYPE>
<HEADER_ID>1</HEADER_ID>
<tITEM_NAME>a</ITEM_NAME>
<ITEM_TYPE>b</ITEM_TYPE>
<SERVICE_DETAIL>
<SERVICE_ID>c</SERVICE_ID>
<SERVICE_DETAILS>
<SERVICE_1>d</SERVICE_1>
<SERVICE_2>e</SERVICE_2>
<SERVICE_3>f</SERVICE_3>
</SERVICE_DETAILS>
</SERVICE_DETAIL>
</HEADER_TABLE_TYPE>
I have the error- the declaration of ... is incomplete or malformed coming from the last type- "Subscriber_T" but I don't see a problem with the syntax. These are the scripts:
CREATE OR REPLACE TYPE Surnames_T AS OBJECT (
Surname varchar (20)
);
/
CREATE OR REPLACE TYPE listSurnames_T
AS Varray(4) of Surnames_T;
/
CREATE OR REPLACE TYPE listTels as object(
Tel number (12)
);
/
CREATE OR REPLACE TYPE listTels_T as Varray(5) of listTels;
/
CREATE OR REPLACE TYPE ADDRESS_T AS OBJECT (
NUM number (6),
STREET varchar (20),
TOWN varchar (20)
);
/
CREATE or replace type TAddress
as table of Address_T;
/
create or replace type Subscriber_T as object(
num_s number(6),
sName varchar(30),
surname listSurnames_T,
Adds TAddress,
DateOfBirth date,
member function cal_Age return number,
phoneNo listTels_T
);
/
show error
I need a fix please!
You have to put member functions after all other fields; you can't sneak a field in at the end:
create or replace type Subscriber_T as object(
num_s number(6),
sName varchar(30),
surname listSurnames_T,
Adds TAddress,
DateOfBirth date,
phoneNo listTels_T,
member function cal_Age return number
);
/
TYPE SUBSCRIBER_T compiled
Obligatory SQL Fiddle.
This is shown in the syntax diagram in the documentation; you can have one or more attributes, and then one or more elements (including functions), but you can't mix them around. Notice which bits have loops, and where they loop back to.