Oracle SQL3 3 nesting tables insert problem - sql

I'm making an SQL3 script where I create types and then create tables and nested tables.
The prolem I'm getting happens when I want to insert a row where it says :
ORA-00932: inconsistent datatypes: expected UDT got CHAR
this is an online reproduction of the problem where the types and tables are already created, you can try to insert:
https://www.tutorialspoint.com/oracle_terminal_online.php?fbclid=IwAR0GgaLe2_GvGsEb80eB-D0uKDSDJDr1WNBPiK3mHQqpJQrtfacQ1cf03NA
the following is the types creation script
CREATE TYPE T_Personne ;
/
CREATE TYPE T_SET_Tag AS TABLE OF Varchar2(30);
/
CREATE TYPE T_Message AS OBJECT (
Texte Varchar2(500),
DateEcrit Date,
Tags T_SET_Tag
);
/
CREATE TYPE T_SET_Message AS TABLE OF T_Message;
/
CREATE TYPE T_Contact AS OBJECT(
Per REF T_Personne,
Depuis Date
);
/
CREATE TYPE T_SET_Contact AS TABLE OF T_Contact;
/
CREATE OR REPLACE TYPE T_Personne AS OBJECT (
Prenom Varchar2(30),
Suit T_SET_Contact,
Ecrit T_SET_Message
);
/
this one is the table creation script
CREATE TABLE TAB_Personne OF T_Personne
NESTED TABLE Suit STORE AS TAB_suit,
NESTED TABLE Ecrit STORE AS TAB_ecrit(
NESTED TABLE Tags STORE AS TAB_Tags
);
and finally the script I'm using to insert my new rows
INSERT INTO TAB_Personne VALUES(
'Baam',
T_SET_Contact(),
T_SET_Message()
);
INSERT INTO TAB_Personne VALUES(
'Rachel',
T_SET_Contact(
(SELECT REF(P)
FROM TAB_Personne P
WHERE P.Prenom='Baam'),
to_date('01/01/2018', 'dd/mm/yyyy')
),
T_SET_Message(
'Paris candidat aux jeux Olympiques 2022',
to_date('01/06/2019', 'dd/mm/yyyy'),
T_SET_Tag('JM2022')
)
);
the error message I'm getting is
1 row created.
'Paris candidat aux jeux Olympiques 2022', *
ERROR at line 10:
ORA-00932: inconsistent datatypes: expected UDT got CHAR
I'd be glad if anyone can guide me through this, thanks.

You are specifying a T_SET_Message collection but you then need T_Message objects within that; you're supplying the attributes of that object type, not an actual object of the type. The first element in the (non-)collection is a string, hence the error you get - you've supplied a string ('Paris...') when it's expecting to see a UDT (T_Message('Paris...', ...)).
You are also doing the same thing with the T_SET_Contact collection.
You need to wrap your current attributes in object constructors; so this works:
INSERT INTO TAB_Personne VALUES(
'Rachel',
T_SET_Contact(
T_Contact(
(SELECT REF(P)
FROM TAB_Personne P
WHERE P.Prenom='Baam'),
to_date('01/01/2018', 'dd/mm/yyyy')
)
),
T_SET_Message(
T_Message(
'Paris candidat aux jeux Olympiques 2022',
to_date('01/06/2019', 'dd/mm/yyyy'),
T_SET_Tag('JM2022')
)
)
);
db<>fiddle

Related

Filter on DATE within custom type?

We have a custom type in our oracle db, let's call it stamp:
CREATE TYPE stamp AS OBJECT(
timestamp DATE,
count INTEGER
)
I'm struggling with just selecting where stamp.timestamp is between certain dates, and I can't really find that use case in the oracle docs.
I thought "just use dot notation", which didn't work. I did solve that one by finding out I need to use an alias in this specific case, so this is my current state (column is called 'when'):
WHERE a.when.timestamp between TO_DATE('2021-06-07', 'YYYY-MM-DD') AND TO_DATE('2021-06-09', 'YYYY-MM-DD');
Except now it says Unsupported column type, which is not very helpful as both the column and entries in the table already exist.
Any idea how to select on a nested date?
You can use (when) to expand your type: DBFiddle
select *
from test
where (when_).timestamp_ between date'2020-02-10'
and date'2020-03-10';
and I wouldn't use reserved/special words as a column/attribute names.
Full example:
CREATE TYPE stamp AS OBJECT(
timestamp_ DATE,
count_ INTEGER
);
create table test (
id int,
when_ stamp
);
begin
insert into test(id,when_) values(1, stamp(date'2020-01-01', 10));
insert into test(id,when_) values(2, stamp(date'2020-02-01', 20));
insert into test(id,when_) values(3, stamp(date'2020-03-01', 30));
insert into test(id,when_) values(4, stamp(date'2020-04-01', 40));
commit;
end;
/
select * from test where (when_).timestamp_ between date'2020-02-10' and date'2020-03-10';

Can't save comma separated number string in varchar2()

I've got a list of items I want to add in a single click, for this purpose I created a table with a column with a type varchar2(4000), in this column I want to list id's that refer to the other table so I can paste the value of this column as a parameter. ex. select t.* from table_name t where t.point_id in (varchar2 string of comma seprated point_ids).
The problem I've got is that when I put more than 1 id in the varchar2 field I get ORA-06502: PL/SQL: numeric or value error: character to number conversion error
How can I avoid this error? My field is varchar2, not number and I don't want it to be converted. I need the value I'm parsing to be saved. ex. (11, 12)
Picture of my Table:
EDIT: Note - My select is working okay, the problem I'm having is with saving the information.
My Insert :
procedure lab_water_pointsgroup (v_group_id lab_water_pointsgroups.group_name%type,
v_group_name lab_water_pointsgroups.group_code%type,
v_group_code lab_water_pointsgroups.lab_points_ids%type,
v_lab_points_ids lab_water_pointsgroups.group_id%type) as
begin
update lab_water_pointsgroups
set group_name = v_group_name,
group_code = v_group_code,
lab_points_ids = v_lab_points_ids
where group_id = v_group_id;
if ( SQL%RowCount = 0 ) then
insert into lab_water_pointsgroups
(group_id, group_name, group_code, lab_points_ids)
values
(v_group_id, v_group_name, v_group_code, v_lab_points_ids);
end if;
end;
Not sure how exactly I can help you here as you gave no example. Have a look at the below demo, maybe the contruct with xmltable solves your problem. HTH KR
create table testtab (id number);
insert into testtab values (1);
select * from testtab where id in ('1'); -- works
select * from testtab where id in (1); -- works
select * from testtab where id in (1,2); -- works
select * from testtab where id in ('1,2'); -- ORA-01722: invalid number
select * from testtab where id in (select to_number(xt.column_value) from xmltable('1,2') xt); -- works
Here is how you defined parameters for your procedure:
v_group_id lab_water_pointsgroups.group_name%type,
v_group_name lab_water_pointsgroups.group_code%type,
v_group_code lab_water_pointsgroups.lab_points_ids%type,
v_lab_points_ids lab_water_pointsgroups.group_id%type
I suspect that you made mistake with types, because id has name type, name has code type etc. So it should be:
v_group_id lab_water_pointsgroups.group_id%type,
v_group_name lab_water_pointsgroups.group_name%type,
v_group_code lab_water_pointsgroups.group_code%type,
v_lab_points_ids lab_water_pointsgroups.lab_points_ids%type
And I suggest to use merge instead of this update / insert, but it's not what you asked for :)
Your error is in that you don't make difference between variable containing comma separated numbers and actual enumeration in the 'in' operator. After your code analize and preparation to execution your statement will be like .. id in ('1,2,3') instead of ..id in (1,2,3), did you notice differnce ? So you need to transform comma separated values into array or in this case into collection. Your code should be like this:
select t.*
from table_name t
where t.point_id in
(select regexp_substr(YOUR_VARCHAR2_COLUMN_VALUE, '[^,]+', 1, level)
from dual
connect by regexp_substr(YOUR_VARCHAR2_COLUMN_VALUE, '[^,]+', 1, level) is not null)

Circular Dependency -Table Insertion Error

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 ;

How to return user-defined type as varchar2?

Let's consider a table with user defined type.
create or replace type reftype is object (id number, name varchar2(40), details varchar2(1000));
create table testref(c1 reftype);
insert into testref values (REFTYPE(4, 'asd', 'aaa'));
insert into testref values (REFTYPE(3, 'asf', 'baa'));
insert into testref values (REFTYPE(2, 'asg', 'aba'));
insert into testref values (REFTYPE(1, 'ash', 'aab'));
/
select * from testref;
Select returns column with objects of user type. When I execute it in SQL*plus I will see:
SQL> select * from testref
REFTYPE(4, 'asd', 'aaa')
REFTYPE(3, 'asf', 'baa')
REFTYPE(2, 'asg', 'aba')
REFTYPE(1, 'ash', 'aab')
How can I write my query to return such output as a text (let's say varchar2).
SQL> select substr(c1,1,4) from testref;
select substr(c1,1,4) from testref
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected CHAR got KACPER.REFTYPE
The same with:
select substr(cast(c1 as varchar2(1000)),1,4) from testref;
And I would like to send string representing user defined type to application as a text not as a UDT. Can you advise me how to write a query that will return varchar2 representaion same as I can see in SQL*PLUS?
EDIT
My real case is using:
create or replace type reftypetab as table of reftype;
and query:
select cast(collect(c1) as reftypetab) from testref;
I would like to have that output either as varchar2: 'KACPER.REFTYPETAB(KACPER.REFTYPE(4,'asd','aaa'),KACPER.REFTYPE(3,'asf','baa'),KACPER.REFTYPE(2,'asg','aba'),KACPER.REFTYPE(1,'ash','aab'))' or as an XML. But when calling:
select xmltype(cast(collect(c1) as reftypetab)) from testref;
I got:
ORA-06553: PLS-306: wrong number or types of arguments in call to 'XMLTYPE'
Do you have any suggestions how can I get XML or text representation of my tabletype?
You can use this one:
SELECT T.c1.ID, T.c1.NAME, T.c1.details
FROM TESTREF T;
If you like to get all in one (XML string) you can also use
SELECT XMLTYPE(c1)
FROM TESTREF;
Another way is this one:
CREATE OR REPLACE TYPE reftype IS OBJECT (ID NUMBER, NAME VARCHAR2(40), details VARCHAR2(1000),
MEMBER FUNCTION TO_VARCHAR2 RETURN VARCHAR2);
CREATE OR REPLACE TYPE BODY reftype IS
MEMBER FUNCTION TO_VARCHAR2 RETURN VARCHAR2 IS
BEGIN
RETURN SELF.ID||','||SELF.NAME||','||SELF.details;
END TO_VARCHAR2;
END;
/
SELECT t.c1.TO_VARCHAR2()
FROM TESTREF t;
Try something like this:
select t.c1.id||','||t.c1.name||','||t.c1.details text
from testref t;
TEXT
----------------
4,asd,aaa
3,asf,baa
2,asg,aba
1,ash,aab
NB For reasons I've never understood, the explicit table alias is mandatory - i.e. the following will not work:
-- No alias:
select c1.id||','||c1.name||','||c1.details text
from testref;
-- Implicit use of table name as alias:
select testref.c1.id||','||testref.c1.name||','||testref.c1.details text
from testref;

Inconsistent datatypes : CAST REF?

I've this schema:
CREATE OR REPLACE TYPE tree_t
/
CREATE OR REPLACE TYPE element_t AS OBJECT (
libelle varchar2(100),
parent REF tree_t,
) NOT FINAL NOT INSTANTIABLE
/
CREATE OR REPLACE TYPE tree_t UNDER element_t()
/
CREATE OR REPLACE TYPE leaf_t UNDER element_t()
/
And I'm trying to insert in this table:
CREATE TABLE elements OF element_t;
For an element_t without parent, no problem :
INSERT INTO elements VALUES (tree_t('first', NULL));
But with a parent :
INSERT INTO elements
VALUES (tree_t('second',
(SELECT REF(e)
FROM elements e
WHERE e.libelle = 'first')));
I've this result:
ORA-00932: inconsistent datatypes: expected REF CINETREE.TREE_T
got REF CINETREE.ELEMENT_T
Can I keep this schema, and how to make insertions?
(with CAST?)
TREAT should do the trick:
INSERT INTO elements
VALUES (tree_t('second',
(SELECT TREAT(REF(e) AS REF tree_t)
FROM elements e
WHERE e.libelle = 'first')));