Assign Multi Dimensional Collection in PLSQL - collections

I have a record:
CREATE OR REPLACE TYPE rec01 IS OBJECT
( -- Business
refund_desc VARCHAR2(20),
percentage VARCHAR2(5),
amount VARCHAR2(25),
pmt_method VARCHAR2(20)
)
And then I make the collection from that record
CREATE OR REPLACE TYPE tbl01 AS TABLE OF rec01
And then from that table I make another one collection
CREATE OR REPLACE TYPE tbl02 AS TABLE OF tbl01
How can I assign the value, for example value of tbl02(1)(2),.?
Better solution is using loop to assign it's value, but how,.?
thanks,.

Here is an example of assigning value to a multilevel collection. Also check Here.
These do not use Objects.

Related

Adapt ON CONFLICT clause to new unique index?

I want to add an extra unique constraint to an existing table. This and other answers say it's not possible with sqlite, and suggest creating an unique index:
ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
This seems to work. However, I'm having trouble with UPSERTs:
INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';
This gives an error:
ON CONFLICT cause does not match any PRIMARY KEY or UNIQUE constraint
Is there any way I could adapt the ON CONFLICT clause of the statement above to work with the new "constraint"?
I tried using new_unique_index, to no avail. If it's impossible, is there any alternative to creating a new table with the new unique constraint and copying the values from the old table into the new one with NULL for the new constraint column? This would be burdensome. I imagine I could create a new table with all of the former's columns, except the old uniques, plus the new unique, and link them somehow, but it sounds messy and I have no idea how to proceed.
Minimum reproducible example:
CREATE TABLE example (foo TEXT, old_unique TEXT, UNIQUE(old_unique));
ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';
Is there any way I could adapt the ON CONFLICT clause of the statement above to work with the new "constraint"?
(old_unique, new_unique) is a not a possible constraint target as there is no index that combines both columns, each is an individual constraint (so you could use one or the other, as my understanding is that you are limited to a single UPSERT clause and a single conflict target).
If instead of :-
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
You used
CREATE UNIQUE INDEX new_unique_index ON example(old_unique,new_unique);
Then the following will work :-
INSERT INTO example (foo,old_unique,new_unique) VALUES('foo','old','new') ON CONFLICT (old_unique,new_unique) DO UPDATE SET foo = 'foo';
(well at least not be rejected due to no covering primary key or index for the given conflict target).
If it's impossible, is there any alternative to creating a new table with the new unique constraint and copying the values from the old table into the new one with NULL for the new constraint column? This would be burdensome.
It's not really burdensome e.g. you could use :-
CREATE TABLE IF NOT EXISTS temp_example (foo, old_unique,new_unique, UNIQUE(old_unique,new_unique));
INSERT INTO temp_example SELECT *,null FROM example;
ALTER TABLE example RENAME TO old_example;
ALTER TABLE temp_example RENAME TO example;
DROP TABLE If EXISTS old_example;
i.e. as you are adding a column and it will be the last column then there is no need to code column names.

Inserting from an object into another object

From table abc i am inserting values in the object abc_type now i'm trying
to insert form abc_type to abc_second object on some condition.While doing
his i'm getting error that this is not a table.Is it even possible to fetch
data from an object and insert into another one.
create table abc(id number,name varchar2(50));
create or replace type abc_obj as object(id number,name varchar2(50) ) ;
create or replace type abc_ref as table of abc_obj;
declare
abc_type abc_ref := abc_ref();
abc_second abc_ref := abc_ref();
begin
select abc_obj(id ,name)
bulk collect into abc_type
from abc;
insert into table(abc_second) select * from abc_type where id=1;
end;
Unfortunately, Oracle user the term "table" in 3, or more, totally different contexts. When you "create table ...' you build the definition of an object in which to persist data, this is the normal use for the term. However, when you use the form "... table of ...' you define an pl/sql collection (array) for holding data inside pl/sql. In this case you have created a "nested table" (3rd use of table). (Note: Some collection types can be declared as column attributes on tables.)
While not identical there are multiple issues with your object definitions as well.
You did not explain the intended use for "second_table" but it seems you merely a
copy of the data from "abc". This can be achieved in multiple ways. If it is basically a one time process then just
create table second_table as select * from abc;
If this is an ongoing action then
create table second_table as select * from abc where 1=0;
-- then when ever needed
insert into second_table select * from abc;
If neither of these satisfy your intended use please expand your question to explain the intended use.

Inserting data into Object type table from another existing table..Oracle 11g

I am trying to insert data into an object type table from another existing table in a stored procedure.
I created the "object" type and it's type "table" as below example.
CREATE OR REPLACE TYPE EXAMPLE AS OBJECT
(
ALL THE COLUMNS,
);
/
CREATE OR REPLACE TYPE EXAMPLE_TABLE AS TABLE OF EXAMPLE;
trying to use this type table to get the data inserted from another table.
---
BEGIN
INSERT INTO EXAMPLE_TABLE (ALL THE COLUMS FROM EXAMPLE)
VALUES (SELECT * FROM EMP_TABLE);
is this possible? let me know, or should I use the "CURSOR" to insert one by one..
please let me know how to achieve this,in the form of syntax
--thank you in advance
Example table is a type so you can't insert anything into it, first you would need to define a variable that would be an instance of your example_table. Then you can use a bulk collect to actually populate your table.
declare
example_tab_inst EXAMPLE_TABLE;
begin
select
EXAMPLE(e.col1,e.col2,e.col3)
bulk collect into example_tab_inst
from emp_table e;
.
.
.

how to insert the field values in the connected openedge database when table and column names are given

I've retrieved the field names of a table by giving the table name directly (INS_TEST is the name of my table). I used columns _Field-Name, _Data-Type of the _Field system table and retrieved the field names and their data types.
I want to use the retrieved field names and insert field values into those fields.
FOR EACH _File WHERE _File-Name = "INS_TEST":
FOR EACH _Field WHERE _File-Recid = RECID(_File):
DISPLAY _Field._Field-Name.
DISPLAY _Field._Data-Type.
ASSIGN _File._File-Name._Field._Field-Name = 1 WHEN (_Field._Data-Type EQ "INTEGER").
END.
END.
But the ASSIGN statement gives an error. Suggestions please!
The following procedure takes a table name, a field name and a character value as parameters. It will update the field in question in the first record of that table with the value provided.
Obviously you could write a more sophisticated WHERE clause and do other things to fancy it up for your specific needs.
procedure x:
define input parameter tbl as character no-undo.
define input parameter fld as character no-undo.
define input parameter xyz as character no-undo.
define variable qh as handle no-undo.
define variable bh as handle no-undo.
define variable fh as handle no-undo.
create buffer bh for table tbl.
create query qh.
qh:set-buffers( bh ).
qh:query-prepare( "for each " + tbl ).
qh:query-open.
do transaction:
qh:get-first( exclusive-lock ).
fh = bh:buffer-field( fld ).
display fh:buffer-value.
fh:buffer-value = xyz.
end.
delete object bh.
delete object qh.
return.
end.
run x ( "customer", "name", "fred" ).
/* prove that we really did change it...
*/
find first customer no-lock.
display name.
Don't use the _field table for this. _file and _field (in fact, any table that starts with underscore) are your meta schema tables. They're your friends in learning dynamic programming or even understanding how your schema is currently defined, but I strongly recommend AGAINST trying to manipulate them yourself. And it doesn't really sound like you're trying to do that anyway, if I understand you correctly.
So once you have ins_test fields, you can do a static assign in a block (again, no need to query or cycle the underscore tables in this case):
CREATE ins_test.
ASSIGN ins_test.field1 = value1
ins_test.field2 = value2
ins_test.field3 = value3 NO-ERROR.
IF ERROR-STATUS:ERROR THEN DO:
/* Treat your error here */
END.
Or, if you're really looking into dynamic assigning (which is going to be harder given you're probably still starting), you need to study dynamic queries and dynamic buffers so you understand those, then you could create the record by getting a handle to the buffer, then assign the table using the BUFFER-FIELD attribute to cycle the field names.
Hope that helps.

Cassandra Select Query using Collection Primary Key in Where Clause

I'm new to Cassandra and I created a table with a frozen collection as the primary key
cqlsh> create table rick_morty (id uuid, name text, adventure text, instigator frozen<set<text>>, PRIMARY KEY((instigator), adventure, name, id));
Now I want to query based on the primary key (instigator) for all of the values held in the collection. I have found that if I just wanted to query on 1 value, I can use CONTAINS 'contained_value', but I want to query on the entire collection.
I've been looking all over to figure out how to do this but I can't find the answer.
Doing something like
const query = 'SELECT name from rick_morty';
retrieves all results but I want to do something like...
const query = 'SELECT name from rick_morty where instigator = ["Rick", "Morty", "Beth"]';
to retrieve all list of names associated with that array of instigators.
Is this possible?? Did I just create my table in an improper way?
Is this possible??
Yes. See #8 here.
"Filter data on a column of a user-defined type. Create an index and then run a conditional query. In Cassandra 2.1.x, you need to list all components of the name column in the WHERE clause."
This should work:
SELECT name from rick_morty where instigator = { 'Rick', 'Morty', 'Beth'};
The following query should work,
SELECT name from rick_morty where instigator contains 'Rick' AND contains 'Morty';
But, This may not be an efficient/proper way to implement as Sets are meant to be used to store/get a set of data for a given primary key.
So, I would recommend you to re-design the data model by denormolise the query into a an additional table in case if this requirement is one of your primary use case.

Resources