I have a problem with SQL Object (ORACLE). :(
I have an abstract type Forum, generalized in ForumCategory, and a type Category :
CREATE OR REPLACE TYPE Forum_t AS OBJECT
(
moderators Users_table_ref,
topics Topics_table,
MEMBER FUNCTION getName RETURN VARCHAR2
)
NOT FINAL NOT INSTANTIABLE;
/
CREATE TABLE Forum OF Forum_t
NESTED TABLE moderators STORE AS Liste_moderators,
NESTED TABLE topics STORE AS Liste_topics
(NESTED TABLE posts STORE AS Liste_posts);
CREATE OR REPLACE TYPE ForumCategory_t UNDER Forum_t
(
category REF Category_t,
OVERRIDING MEMBER FUNCTION getName RETURN VARCHAR2
);
/
CREATE OR REPLACE TYPE BODY ForumCategory_t AS
OVERRIDING MEMBER FUNCTION getName RETURN VARCHAR2 IS
c Category_t;
BEGIN
SELECT DEREF(SELF.category) INTO c FROM DUAL;
RETURN c.name;
END getName;
END;
/
CREATE OR REPLACE TYPE Category_t AS OBJECT
(
name VARCHAR2(60)
);
/
CREATE TABLE Category OF Category_t
(
CONSTRAINT PK_CAT_NAME PRIMARY KEY(name)
);
I want to make a trigger after insert on table Category which insert a ForumCategory_t on table Forum.
I have this code :
CREATE OR REPLACE TRIGGER Category_insert
AFTER INSERT ON Category
FOR EACH ROW
DECLARE
ref_cat REF Category_t;
BEGIN
SELECT REF(c) INTO ref_cat
FROM Category c
WHERE c.name = :NEW.name;
INSERT INTO Forum VALUES(ForumCategory_t(Users_table_ref(),Topics_table(),ref_cat));
END;
/
The beginning don't work, I cannot select REF of the inserted Category (it's work outside the trigger).
Please, I need help ^^
PS : Sorry for my english
Related
I have this DB for movie management in cinemas:
FILM (ID_FILM, TITLE, DIRECTOR_NAME, PRODUCTION-BUDGET, RELEASE-DATE)
SCREENING(ID_SCREEN, ID_FILM*, SCREEN_DATE, ROOM, City)
SEEN (ID_SEEN, SPECTATOR_NAME, ID_SCREEN*, TICKET-PRICE).
I need to complete the Film type with the MySpectators method returning the whole (without duplicates) of its spectators. This is what I wrote for the signature and the body of this method :
create type tset_spectator as table of varchar(100);
/
alter type tfilm add member function MySpectators return tset_spectator cascade;
create or replace type body tfilm as member function MySpectators return tset_spectator
is
spectatorsfilms tset_spectator;
Begin
select CAST(MULTISET(
select deref(deref(value(p)).screening_seen)
from film f, table(f.film_screening) p
where f.ID_FILM=self.ID_FILM) as tset_spectator)
into spectatorsfilms
from dual;
return spectatorsfilms;
end;
End;
/
I got this error that I couldn't fix:
PL / SQL: ORA-00932: inconsistent data types; expected: REF; obtained: DBACINEMA.TSET_REF_SEEN
N.B I already created types, tables and nested tables before.
Thank you for your help.
You haven't showed your DBACINEMA.TSET_REF_SEEN, so I can only guess that is a collection and you need to use one more table():
create or replace type body tfilm as member function MySpectators return tset_spectator
is
spectatorsfilms tset_spectator;
Begin
select CAST(MULTISET(
select deref(value(scr_seen))
from film f, table(f.film_screening) p
,table(deref(value(p)).screening_seen) scr_seen
where f.ID_FILM=self.ID_FILM
) as tset_spectator)
into spectatorsfilms
from dual;
return spectatorsfilms;
end;
End;
/
I'm making a table which contains nested table:
create DOCUMENT as OBJECT (
DOC_ID NUMBER,
DESCRIPTION VARCHAR(1000));
create type documents_t is table of DOCUMENT;
create table projects (
ID NUMBER GENERATED ALWAYS AS IDENTITY ,
DOCUMENTS documents_t)
NESTED TABLE DOCUMENTS STORE AS documents_nested(
(PRIMARY KEY(nested_table_id, DOC_ID)) ORGANIZATION INDEX);
This works ok, but I can't seem to find how to make the nested table's primary key as identity column. any suggestions?
Thanks
Please find the code snippet,
CREATE SEQUENCE seq_documents
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
CREATE OR REPLACE TYPE documents_q AS OBJECT
(
doc_id NUMBER,
description VARCHAR2(1000),
CONSTRUCTOR FUNCTION documents_q(p_description VARCHAR2) RETURN SELF AS RESULT
);
CREATE OR REPLACE TYPE BODY documents_q AS
CONSTRUCTOR FUNCTION documents_q(p_description VARCHAR2) RETURN SELF AS RESULT IS
BEGIN
self.doc_id := seq_documents.nextval;
self.description := p_description;
RETURN;
END;
END;
/
CREATE TYPE documents_t AS TABLE OF documents_q;
create table projects (
id NUMBER GENERATED ALWAYS AS IDENTITY ,
documents documents_t)
NESTED TABLE documents STORE AS documents_nested(
(PRIMARY KEY(nested_table_id, doc_id)) ORGANIZATION INDEX);
INSERT INTO PROJECTS(documents) VALUES (documents_t(documents_q('Description One'),documents_q('Description Two')));
SELECT * FROM projects;
Please let me know if it gives you the solution. Thank you
If you want another solution without constructor (because using constructor adds more maintenance)
I took #Sujitmohanty30 idea and used the sequence in the insert statement. It makes code more easy to maintain, but force you to use sequence on insert and insert one item at each query (because "sequence.nextval" don't get incremented in same query):
CREATE SEQUENCE documents_seq NOCACHE;
/
CREATE TYPE document_type AS OBJECT (
doc_id NUMBER,
description VARCHAR2(1000)
);
/
CREATE TYPE documents AS TABLE OF document_type;
/
create table projects_docs (
id NUMBER GENERATED ALWAYS AS IDENTITY ,
docs documents)
NESTED TABLE docs STORE AS docs_nested(
(PRIMARY KEY(nested_table_id, doc_id)) ORGANIZATION INDEX);
/
INSERT INTO projects_docs (docs) VALUES(
documents(document_type(documents_seq.nextval, 'doc')));
/
select p.id, d.* from projects_docs p, table(p.docs) d;
I want to insert data into table but got below error..Can any one help me..
CREATE OR REPLACE TYPE TEST_TYP FORCE IS OBJECT
("id" VARCHAR(5000 NULL)
NOT FINAL;
CREATE OR REPLACE TYPE TEST_TAB is table of REF TEST_TYP;
CREATE OR REPLACE TYPE TEST1_TYP FORCE IS OBJECT
("id" VARCHAR2(500) NULL,
"extension" "TEST_TAB" NULL )
NOT FINAL;
CREATE TABLE "TEST_OBJ_TABLE" OF "TEST1_TYP"
NESTED TABLE "extension" STORE AS "Allin"
When I try to insert using this statementL
insert into "TEST_OBJ_TABLE" ("id","extension")
VALUES(
'0FE71A85',
"TEST_TAB"("TEST_TYP"( '0FE71A8'))
);
It throws this error
Error at Command Line : 59 Column : 12
Error report -
SQL Error: ORA-00932: inconsistent datatypes: expected REF SUB_HWOW.TEST_TYP got SUB_HWOW.TEST_TYP
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
You have to modify object TEST_TYP -> varchar2 has to be max 4000.
You have to store this object in db.
Create object table for TEST_TYP
create table t_for_test_type of TEST_TYP;
To obtain object reference, the object have to be save in db table. In your case:
declare
v_ref_to_test_type1 ref TEST_TYP;
begin
insert into t_for_test_type t values('abcd1') return ref(t) into v_ref_to_test_type1;
end:
Join all parts together.
declare
v_ref_to_test_type1 ref TEST_TYP;
v_ref_to_test_type2 ref TEST_TYP;
begin
insert into t_for_test_type t values('abcd1') return ref(t) into v_ref_to_test_type1;
insert into t_for_test_type t values('abcd2') return ref(t) into v_ref_to_test_type2;
insert into TEST_OBJ_TABLE values (TEST1_TYP('abcd',new TEST_TAB(v_ref_to_test_type1,v_ref_to_test_type2)));
end;
Query table.
select t."id",x.column_value from TEST_OBJ_TABLE t, table(t."extension") x it returns id + ref to other object
Viewing the referenced object.
select t."id",deref(x.column_value) from TEST_OBJ_TABLE t, table(t."extension") x
Note1. You should avoid declaring attribute using double quote. Db becomes case sensitive and it's not normal situation :)
Note2. I don't know why code formatting is not working today
Question. Why are you trying to use such complicated construction?
Changed the original answer. The quotes are doing you no favors - nor was calling your column names id. Removed the REF reference.
CREATE OR REPLACE TYPE TEST_TYP FORCE IS OBJECT
(id1 VARCHAR(4000) NULL)
NOT FINAL;
CREATE OR REPLACE TYPE TEST_TAB is table of TEST_TYP;
CREATE OR REPLACE TYPE TEST1_TYP FORCE IS OBJECT
(id2 VARCHAR2(500) NULL,
extension TEST_TAB NULL )
NOT FINAL;
CREATE TABLE TEST_OBJ_TABLE OF TEST1_TYP
NESTED TABLE extension STORE AS Allin ;
insert into TEST_OBJ_TABLE ( ID2, EXTENSION)
VALUES(
'0FE71A85',
TEST_TAB(TEST_TYP( '0FE71A8'))
);
SELECT * FROM TEST_OBJ_TABLE ;
I'm trying to return a list of char in a function PL/SQL with Oracle 11, but without succes.
I've got a few difficulties for understand their running...
For example, i have this code created for test:
create type test is table of varchar(500);
/
CREATE OR REPLACE FUNCTION test2 (id INT)
RETURN test
is
tt_t test;
BEGIN
SELECT descriptifSpecifique INTO tt_t(1)
FROM DECOMPOSE
where idRecette=id
AND idEtape=2;
SELECT descriptifSpecifique INTO tt_t(2)
FROM DECOMPOSE
where idRecette=id
AND idEtape=3;
RETURN tt_t;
END;
/
show errors function test;
The fonction is created without compilation's problem, but at the execution, I have this message: ORA-06531: Reference to uninitialized collection.
Also, how can I return a type (with a varchar and a int generated by a select for example) IN PL/SQL. Because when I try to make a declaration of type with RECORD, and RETURN this type, I have compilation's problem because type is not declarated...
Thank you
You are basically doing it correctly. But you need to EXTEND your collection before you put new elements into it.
Personally, I prefer to BULK COLLECT into the collection to avoid having to EXTEND and manage the entries at each index. Like this (code untested):
CREATE OR REPLACE FUNCTION test2 (id INT)
RETURN test
is
tt_t test;
BEGIN
SELECT descriptifSpecifique
BULK COLLECT INTO tt_t
FROM DECOMPOSE
where idRecette=id
AND idEtape IN (2,3)
ORDER BY idEtape;
RETURN tt_t;
END;
/
To return a TYPE having multiple columns, you need to create two types: an OBJECT type and a TABLE OF that object type.
Like so,
CREATE TYPE test_rec IS OBJECT ( a_varchar VARCHAR2(500), a_number NUMBER);
CREATE TYPE test_tbl IS TABLE OF test_rec;
Then, you can modify your function accordingly:
CREATE OR REPLACE FUNCTION test2 (id INT)
RETURN test_tbl
is
tt_t test_tbl;
BEGIN
SELECT test_rec(idEtape, descriptifSpecifique)
BULK COLLECT INTO tt_t
FROM DECOMPOSE
where idRecette=id
AND idEtape IN (2,3)
ORDER BY idEtape;
RETURN tt_t;
END;
/
Hey there I have a function, and part of the function is to make sure that the selected value is within the passed in table of varchar2s. To start I declare a varchar2 table type like so.
create or replace type Varchar2Table is table of varchar2(200)
Then I have the function which accepts the nested table parameter and has a select statement on them.
function SelectPeople(inputNames Varchar2Table) return People
begin
--stuff
select * from person_table where name in inputNames; --line of interest
--more stuff
end;
This doesn't seem to work though, I get the following error:
ORA-00932: inconsistent datatypes: expected NUMBER got
ENGSPL5.VARCHAR2TABLE
Any suggestions?
The TABLE operator allows nested tables to be used in SQL statements. The function was also missing an IS and an INTO.
create or replace type Varchar2Table is table of varchar2(200);
create table person_table(id number, name varchar2(100));
create or replace function SelectPeople(inputNames Varchar2Table) return number
is --Missing "IS".
type numberTable is table of number; --Need a collection to store results.
numbers numberTable;
begin
select id
bulk collect into numbers --Missing "INTO".
from person_table
where name in (select column_value from table(inputNames)); --Missing "TABLE".
--Alternatively a multiset condition can be used.
--where name member of inputNames;
--Dummy return value to make the function compile.
return 1;
end;
/