add values to nested table from another table (oracle) - oracle

I am trying to insert values to a nested table with an object of another table. This is what I'm trying (Sorry, I'm new working with dbs):
INSERT INTO Ocurrences (..., oSpace) VALUES
(other inserts,
/* insert I don't know to do it to nested table oSpaces */
);
How I could add a value in oSpaces inserting an object from table Spaces?
Thanks.

Just use a collection of REFerences:
INSERT INTO Ocurrences (
CCase,
/* ... Other column identifiers ..., */
oSpaces
) VALUES (
'abc',
/* ... Other column values ..., */
tSpace(
(SELECT REF(s) FROM spaces s WHERE s.intcode='1')
)
);
db<>fiddle here
As an aside, '20/02/2020' is not a DATE data-type, it is a string literal and relies on an implicit string-to-date conversion. This implicit conversion will fail if the user's NLS_DATE_FORMAT session parameter does not match your string's format and since any user can change their session parameters at any time then this is not something you should rely on.
Instead, you should use:
A date literal DATE '2020-02-20'; or
An explicit conversion TO_DATE('20/02/2020', 'DD-MM-YYYY').

Related

Delete element from jsonb array in cockaroachdb

I got field with jsonb tags: [{"value": "tag1"}]
I need to do something like this update table1 set tags = tags - '{"value": "tag1"}' - but this don't work
What query should I execute to delete element from array?
Assuming your table looks like
CREATE TABLE public.hasjsonb (
id INT8 NOT NULL,
hash JSONB NULL,
CONSTRAINT hasjsonb_pkey PRIMARY KEY (id ASC)
)
you can do this with the following statement:
INSERT INTO hasjsonb(id, hash)
(SELECT id,array_to_json(array_remove(array_agg(json_array_elements(hash->'tags')),'{"value": "tag1"}'))
FROM hasjsonb
GROUP BY id
)
ON CONFLICT(id) DO UPDATE SET hash = jsonb_set(hasjsonb.hash, array['tags'], excluded.hash);
The actual json operation here is straightforward, if longwinded. We're nesting the following functions:
hash->'tags' -- extract the json value for the "tags" key
json_array_elements -- treat the elements of this json array like rows in a table
array_agg -- just kidding, treat them like a regular SQL array
array_remove -- remove the problematic tag
array_to_json -- convert it back to a json array
What's tricky is that json_array_elements isn't allowed in the SET part of an UPDATE statement, so we can't just do SET hash = jsonb_set(hash, array['tags'], <that function chain>. Instead, my solution uses it in a SELECT statement, where it is allowed, then inserts the result of the select back into the table. Every attempted insert will hit the ON CONFLICT clause, so we get to do that UPDATE set using the already-computed json array.
Another approach here could be to use string manipulation, but that's fragile as you need to worry about commas appearing inside objects nested in your json.
You can use json_remove_path to remove the element if you know its index statically by passing an integer.
Otherwise, we can do a simpler subquery to filter array elements and then json_agg to build a new array.
create table t (tags jsonb);
insert into t values ('[{"value": "tag2"}, {"value": "tag1"}]');
Then we can remove the tag which has {"value": "tag1"} like:
UPDATE t
SET tags = (
SELECT json_agg(tag)
FROM (
SELECT *
FROM ROWS FROM (json_array_elements(tags)) AS d (tag)
)
WHERE tag != '{"value": "tag1"}'
);

i got a error ORA-01747 when insert data into table

i got trouble when insert data using this query :
INSERT ALL
INTO obat ('id_obat','nama_obat','tanggal_kadarluarsa','stock','harga')
VALUES (1, 'Indomethacin', '2023-09-01', 50, 3000)
SELECT * FROM dual;
this is the table query :
CREATE TABLE obat (
id_obat INTEGER NOT NULL,
nama_obat VARCHAR2(255) NOT NULL,
tanggal_kadarluarsa DATE NOT NULL,
stock INTEGER NOT NULL,
harga NUMBER(20, 2) NOT NULL,
CONSTRAINT obat_pk PRIMARY KEY ( id_obat )
);
is somethin wrong with my code?
Single quotes are for string literals; identifiers (e.g. column names) should be in double quotes - but only have to be if they were created as quoted identifiers, and then the case of the name has to match the data dictionary name exactly. Yours are not quoted identifiers in the create statement, so you can just do:
INSERT ALL
INTO obat (id_obat,nama_obat,tanggal_kadarluarsa,stock,harga)
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
SELECT * FROM dual;
If you really wanted to quote them then you would need to do (including the table name to demonstrate, as the same rules apply):
INSERT ALL
INTO "OBAT" ("ID_OBAT","NAMA_OBAT","TANGGAL_KADARLUARSA","STOCK,HARGA")
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
SELECT * FROM dual;
but that's just more typing and arguably maybe harder to read, and easier to get wrong.
You can read more about quoted and non-quoted identifiers in the documentation.
With a single row you don't really need ALL, you can also do:
INSERT INTO obat (id_obat,nama_obat,tanggal_kadarluarsa,stock,harga)
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
Note that I've added the DATE keyword to these statements; '2023-09-01' is not a date, it's a string literal, so you're relying on Oracle implicitly converting that to an actual date, based on your current session NLS settings. With DATE '2023-09-01' that is now a date literal. Again, there is more in the documentation.

Insert records into collection type Oracle

I want to inserted into my collection some SQL records, but I can not. I'm a beginner. Can you help me ?
This is my tables :
CREATE TYPE article_type AS OBJECT (idA CHAR(10), nomA CHAR(10), prixA CHAR(10) )
CREATE TYPE facture_type AS OBJECT (idF CHAR(10), dateFact DATE)
CREATE TYPE ens_collection_fact AS OBJECT (refFact facture_type, refArticle article_type)
CREATE TYPE collection_fact AS TABLE OF ens_collection_fact
CREATE TYPE client_type AS OBJECT (idC NUMBER, nomC CHAR(10),adresse CHAR(10), Compose collection_fact )
CREATE TABLE Article OF article_type
CREATE TABLE Facture OF facture_type
CREATE TABLE Client OF client_type (PRIMARY KEY(idC)) NESTED TABLE Compose STORE AS temp
This is my query that I want to insert, but I have an error from the Oracle : ORA-02315
INSERT INTO ECOLER.CLIENT VALUES
(100, 'Jules Verne', '1', Collection_fact(Ens_collection_fact(reffact('A','2002-12-10'), ens_collection_fact(refarticle('D','E','F'))) ))
Thank in advance
reffact and refarticle are identifiers for objects within other objects, not types; you need to refer to the actual types. You also need to supply both values for each Ens_collection_fact attribute for the default constructor; you can pass null if you only want one or the other:
INSERT INTO CLIENT VALUES
(100, 'Jules Verne', '1',
Collection_fact(
Ens_collection_fact(facture_type('A',date '2002-12-10'), null),
Ens_collection_fact(null, article_type('D','E','F'))
)
)
Also notice that I've added the date keyword so it's providing an actual date literal rather than a string, which would be converted - if you're lucky - with your session NLS settings.
This will still error because 'Jules Verne' is 11 characters and you've defined the name attribute as 10 characters/bytes, but it will work with a shorter string literal.
db<>fiddle

insert values in table with out some columns that may change time to time

insert values in table contain 5 column some times insert with 3 columns and some time all 5 columns data come from front end is not constant dependent upon user insert in front end?
if 4 column value no value for one column and 3 column and 2 column no value also we need to insert value in the table ?
Specify all the columns in your insert statement. The parameters to which you pass null values will be stored as null in the table. There's no need to change your insert statement based on which parameters have non-null values.
create or replace procedure insert_stuff(i_input1 in varchar2, i_input2 in
varchar2... i_input10 in varchar2)is
begin
insert into my_table (col1, col2... col10) values(i_input1, i_input2...
i_input10);
end;
If you are looking for query, then use syntax:
insert into tablename(columnlist seperated by comma) values (values list seperated by comma).
For Example:
insert into TableName(column1_name,column2_name) values(val1,val2);
Use your stored procedure in this way:
create or replace
FUNCTION testFunction
(
field1 IN NUMBER DEFAULT NULL,
field2 IN NUMBER DEFAULT NULL,
field3 IN NUMBER DEFAULT NULL
)
RETURN NUMBER
AS
BEGIN
// your insert query goes here.
END;
If the value for any of the field is not assigned then, it will automatically assign the default value i.e. NULL. Just have a check and i hope it will help you.:)

(Oracle) How to extract a specialized UDO from a object table based on a generalized UDO?

I apologize in advance for not knowing the terminology, but here it goes:
How do I extract a specialized UDO (UDO= user defined object & specialized= that 'extends' or is 'under' another UDO) that I inserted in a object table defined for a generalized UDO (generalized - higher in the same UDO hierarchy).
Details:
CREATE OR REPLACE TYPE GENERIC_UDO AS OBJECT (
atribute_1 TYPE,
...
atribute_n TYPE2, //TYPE2 is a nested table
) NOT FINAL NOT INSTANTIABLE;
CREATE OR REPLACE TYPE SPECIALIZED_UDO UNDER GENERIC_UDO (
atribute_1 TYPE,
...
atribute_q TYPE3, //TYPE3 is also a nested table
) FINAL INSTANTIABLE;
CREATE TABLE TBL_GENERIC_UDO OF GENERIC_UDO
( CONSTRAINT PK...)
... //other nested tables
NESTED TABLE atribute_n STORE AS atribute_n_nst;
So this works:
INSERT INTO TBL_GENERIC_UDO values (new TBL_GENERIC_UDO(...)); because TBL_GENERIC_UDO is 'under' GENERIC_UDO.
A 'select * from TBL_GENERIC_UDO' shows me as columns just the GENERIC_UDO atributes (as expected!)
So how do I extract or extract and convert, because I need to read back the inserted SPECIALIZED_UDO.
I payed a bit with:
VALUE(x): SELECT VALUE(tgo) FROM TBL_GENERIC_UDO tgo;
TREAT(x as Y): SELECT TREAT(VALUE(tgo) as SPECIALIZED_UDO) FROM TBL_GENERIC_UDO tgo;
and no good results. Actually in booth cases I get
SCHEMANAME.SPECIALIZED_UDO(values, values,..., null)
oracle.sql.STRUCT#54faa2
In the first case, when I did the insert, the corespondent value for atribute_q was set to null, in the second one it was a proper value, ex: SPECIALIZED_UDO('value1','value1',...)
I am asumming thats because TBL_GENERIC_UDO doesnt have a store clause for atribute_q from SPECIALIZED_UDO.
So anyone thoughts, explanations would be appreciated.
Solved it myself! Wasn't that hardcore as I expected. First I thought that Oracle will 'truncate' when inserting a specialized UDO into the table defined for a generic UDO, and in my case the specialized UDO had additionally another nested table as a atribute, but it doesn't.
Check code example, last line is the most important one:
CREATE OR REPLACE TYPE OBJ_TBL_TEXT IS TABLE OF VARCHAR2(100);
CREATE OR REPLACE TYPE OBJ_CONTAINER1 AS OBJECT (
ATRIBUTE NUMBER(6),
TBL_TEXT OBJ_TBL_TEXT
) NOT FINAL NOT INSTANTIABLE;
CREATE OR REPLACE TYPE OBJ_CONTAINER2 UNDER OBJ_CONTAINER1(
SECOND_TBL_TEXT OBJ_TBL_TEXT
) FINAL INSTANTIABLE;
CREATE TABLE TBL_CONTAINER1 OF OBJ_CONTAINER1
( CONSTRAINT PK_TBL_CONTAINER1 PRIMARY KEY(ATRIBUTE))
NESTED TABLE TBL_TEXT STORE AS TBL_TEXT_NST;
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(1,null,null));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(2,null, OBJ_TBL_TEXT('VAL1','VAL2')));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(3,OBJ_TBL_TEXT('VAL3','VAL4'), null));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(4,OBJ_TBL_TEXT('VAL5','VAL6'), OBJ_TBL_TEXT('VAL7','VAL8')));
--------------------------------------------------------------------------------
SELECT * FROM TBL_CONTAINER1;
SELECT VALUE(tc) FROM TBL_CONTAINER1 tc;
SELECT TREAT(VALUE(tc) as OBJ_CONTAINER2).SECOND_TBL_TEXT FROM TBL_CONTAINER1 tc;
First select will display as columns just the atributes from the OBJ_CONTAINER1, like:
ATTRIBUTE| TBL_TEXT
--===============--
- 1 (null)
- 2 (null)
- 3 VARCHAR(VAL3,VAL4)
- 4 VARCHAR(VAL5,VAL6)
Second one looks weirder
VALUE(TC)
--=====--
DATAMODELER.OBJ_CONTAINER2(1,null,null)
oracle.sql.STRUCT#57ac8e
oracle.sql.STRUCT#1df6f
oracle.sql.STRUCT#f40801
VALUE - returns the object instance for a row of an object table as associated with the correlation_variable (table alias)
Third one lets me have access to nested attributes not mention in the nested clause in the creation of TBL_CONTAINER1.
TREAT(VALUE(tc) as OBJ_CONTAINER2).SECOND_TBL_TEXT
--==============================================--
(null)
VARCHAR(VAL1,VAL2)
(null)
VARCHAR(VAL7,VAL8)
It is exactly what I needed. Dont know yet how Oracle stores the additional attributes, and don't care. Though to share the solution...

Resources