construct an MCD (merise) where a table contain columns from the content of another table - oracle

i'am facing a problem while trying to make a conception for a school project.and i have two question.
1/
is it possible with oracle to do something like this : https://mariadb.com/kb/en/dynamic-columns/
2/
how can i make a modelisation for that with an MCD (method merise ).
thanks

Quote from your link: "It works by storing a set of columns in a blob and having a small set of functions to manipulate it.". I don't see an obvious reason why you couldn't write something similar for Oracle (or any other relational database).
Alternatively, take a look at EAV, which is a more traditional solution for dynamic columns.
Sorry, I'm not familiar with Merise.

1/ Oracle is not made for creating dynamic columns, but you can do it by using PL/SQL functions (but not while querying with SQL):
create or replace procedure add_table_column(table_name varchar2, column_name varchar2, column_type varchar2)
is
v_script varchar2(4000);
begin
v_script := 'alter table '||table_name||' add '||column_name||' '||column_type;
execute immediate v_script;
end;
/
You can call it this way:
begin
add_table_column('toto','test','number');
end;
/
2/ Merise method is not made for "dynamic objects" as you must begin with a complete data dictionary.
How is your object dynamic, and why do you have to add columns?
You can always get a solution to work by using "regular" tables and relationships.
It sounds like you should start by analyzing the technical implementation in mind. MERISE says to analyze your data model first and start to think about technical solutions after.

Related

Oracle Forms compiler mark a type as function

I'm making a procedure inside an Oracle Form that calls a backtracking which inserts in a table (the solution table). That backtracking is fed by a varray (ítem_array) of ítems (beans). Problem is the compiler says that there is no function name ítem.
existing objects in the database:
CREATE TYPE item IS object( NUM_OPERACIO NUMBER, TITULS NUMBER);
CREATE TYPE item_array IS VARRAY(1000) OF item;
create table my_table (NUM_OPERACIO NUMBER, TITULS NUMBER);
insert into my_table ( NUM_OPERACIO,TITULS ) values (1,10);
insert into my_table ( NUM_OPERACIO,TITULS ) values (2,20)
insert into my_table ( NUM_OPERACIO,TITULS ) values (3,30)
procedure
PROCEDURE solver
IS
arr item_array;
BEGIN
SELECT item( NUM_OPERACIO,TITULS )
BULK COLLECT INTO arr
FROM my_table;
delete from solucion ;
backtra(arr,1,0,30);
END;
What can I do to solve this?
That is a PLS error number. From the documentation:
"PLS-00591: this feature is not supported in client-side programs
Cause: One of the following features was used in a wrong context: pragma AUTONOMOUS_TRANSACTION, dynamic SQL statements, (e.g. EXECUTE IMMEDIATE), and bulk binds. These listed features can only be used in server-side programs but not client-side programs."
Your code uses a bulk-bind, so the error fits. Forms PL/SQL and database PL/SQL are similar but they use different engines, and features supported in both is only a sub-set of all features in either. The solution is to pass the array population into a database procedure and call it from Forms as needed.
Without knowing precisely what problem you're trying to solve, it's harder to give a better answer.

Oracle multiple cursors with the same "WHERE" clause

I need to write a script with an embedded PL/SQL that opens a few cursors and loops through records fetched performing some actions.
All cursors have part of their WHERE a condition that look like this: AND table_name IN ('table_one', 'table_two' ... 'last_table_from_a_long_list')
Because the same list of tables is used everywhere I would prefer not to repeat myself but rather to declare the list of tables somewhere and reuse it in the each cursor definition. Ideally you would put those table names in a real table and everything would work OK; however that script will run in production and creating/dropping tables for this purpose is not an accepted practice. The same restriction would apply about creating a user defined type of table_name and another one as a TABLE OF table_name.
Just wondering if there are some PL/SQL tricks that would help me achieve the same thing. Repeating the long list of tables a dozen of times would make that code look quite bad. This said my script is an "one off" thing so maybe I am worrying too much. There is still the professional "how to" curiosity though.
Thank you in advance for your inputs.
Short answer: repeat the code.
Longer answer: not repeating the code is more work than just biting the bullet and dealing with a little less-than-perfectly elegant code.
Longest answer: if you really need to insist on doing this then look into using dynamically-created SQL - build your SELECT statement(s) out of strings, then either use the OPEN cursor FOR sqlString, FETCH cursor INTO..., and CLOSE cursor statements, or for extra karma and a pile of difficulty study up on the DBMS_SQL package - and may C͡͏ţ͘húl͞ḩ̸u҉͝ have mercy upon your soul.
Best of luck.
Couple of options you can try
EXECUTE IMMEDIATE
-- Cursor Example
sql_stmt := 'SELECT * FROM emp WHERE empno = :id';
EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id;
Another option is DBMS_SQL
CREATE OR REPLACE PROCEDURE DYNSQL AS
cur integer;
rc integer;
BEGIN
cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur, 'CREATE TABLE X (Y DATE)', DBMS_SQL.NATIVE);
rc := DBMS_SQL.EXECUTE(cur);
DBMS_SQL.CLOSE_CURSOR(cur);
END;
You can google with these key words and you will find many examples.

Hide sql from a view

for many reasons, we are protecting our Intellectual Property at its greatest and we already obfuscate and wrap our logic. Everything runs fine.
We have a concern about the views. In some cases we give to our clients some views based on their specific needs. That way we can offer 'em the right results. Otherwise, they sometimes try to build their own sql and they get wrong answers.
Is it possible to fill a materialized view based on a package or procedure? I understand that only a function can return something but I am maybe missing something. My actual alternative is to fill a table via a procedure but I am uncomfortable with that.
We are actually using Oracle 11
Any idea is welcome. Thanks!
You can provide a function which retruns a Nested Table.
CREATE TABLE SECRET_TABLE (col_1 NUMBER, col_2 VARCHAR2(10));
CREATE OR REPLACE TYPE t_secret_table_rec AS OBJECT (col_1 NUMBER, col_2 VARCHAR2(10));
CREATE OR REPLACE TYPE t_secret_table AS TABLE OF t_secret_table_rec;
CREATE OR REPLACE FUNCTION GetData RETURN t_secret_table AS
res t_secret_table;
BEGIN
-- Wrap this function
SELECT t_secret_table_rec(col_1, col_2)
BULK COLLECT INTO res
FROM SECRET_TABLE;
RETURN res;
END;
Then you can select the data like this:
SELECT * FROM TABLE(GetData);
However, it's quite some effort and you may face some problems regarding performance.

ANYDATA with Collections based on rowtype

I just discovered Oracle's ANYDATA and ANYTYPE and thought it would be useful to generic-ify some very repetitive code I have. I tried a very simple code sample that looks like this:
declare
--simple test query
cursor myCurs is
select sysdate from dual;
type t_arr is table of myCurs%rowtype;
v_arr t_arr;
v_anydata ANYDATA;
begin
open myCurs;
fetch myCurs bulk collect into v_arr;
close myCurs;
dbms_output.put_line(v_arr.count || ' records');
v_anydata := ANYDATA.convertCollection(v_arr);
dbms_output.put_line(anydata.gettypename(v_anydata));
end;
/
Running this code gives me the error "ORA-22370: incorrect usage of method ORA-22370 incorrect ussage of method ConvertCollection" (Yes, it actually repeats ORA-22370).
My question is: Is it possible to use ANYDATA on collections of rowtypes? I ask this because all examples I've seen of ANYDATA (so far) with collections use object types, none use rowtypes, but I haven't seen anything (yet) that explicitly says that rowtypes can't be used.
My goal was to clean up some very repetitive bulk-collect/insert code that does the same thing over and over, but with different cursors for different tables.
(Oracle 10g)
ANYDATA works with SQL data_types, i.e. anything you could use to define a table column.
%ROWTYPE is a PL/SQL construct, and so is not recognised by the SQL engine. If you think about the dynamic nature of %ROWTYPE you'll be able to figure out why.
Wanting to clean up repetitive code is a noble idea. I have previously implemented an ETL processor in SQL Types which used a supertype Object to own the generic processing, and subtypes to execute table specific code (such as inserts). These subtypes are completely generatable: not as slick as a dynamic %ROWTYPE implementation would have been, but still easy enough.

Write Oracle Procedure To Accept List of Items used in Select

There have been a couple of hints that seem to have gotten me close here, but with some unique issues, I'm hoping this question is distinguishing enough to merit its own posting.
For starters here's what I have. I have an Oracle procedure that returns a standard REF CURSOR, and this REF CURSOR is passed back to my application. The REF CURSOR is a list of lookup IDs.
I then want to take this list and bring it to another data store and use it in a select statement. It will absolutely be possible to accomplish this by looping through the REF CURSOR, but I'm hoping to avoid that. I would much rather be able to write a SELECT...WHERE lookup_id IN result_ref_cursor OR SELECT...WHERE EXISTS...
First is this possible or should I just try a less than elegant solution? If it is possible, any hints as to where I should get started looking?
I'm relatively new to Oracle, but fairly experienced in RDBMs in general, so feel free to just through some links at me and I can study up. Much appreciated
Why kurosch didn't put his response as an "answer" I'll have no idea.
So, what you do is define a SQL type which describes one row of the output of the ref cursor, and also a SQL type which is a table of the previous. Then, you'll create a pipelined function which returns the rows returned by the ref cursor. This function can then be used in a standard SQL. I'm borrowing from Ask Tom on this one.
create or replace type myLookupId as object ( id int)
/
create or replace type myLookupIdTable as table of myLookupId
/
create or replace function f return myLookupIdTable PIPELINED is
l_data myLookupId;
l_id number;
p_cursor SYS_REFCURSOR;
begin
p_cursor := function_returning_ref_cursor();
loop
fetch p_cursor into l_id;
exit when p_cursor%notfound;
l_data := myLookupId( l_id );
pipe row (l_data);
end loop;
return;
end;
/
And now a sample query...
SELECT *
FROM SOME_TABLE
WHERE lookup_id in (SELECT ID FROM table(f));
Sorry if the code isn't exactly right, I don't have the DB to test right now.
There are several directions you could go with this, but I did a search on the specific solution you want and it seems like no-one has done it often enough to show up there. What you can do is search the oracle metalink - that is usually really good at finding obscure answers. (Though you do need a service agreement - just found out that mine expired :( )
Other possible solutions:
Create a link between the data stores so that you can do the select in the plsql directly
Create a function in Java that loops through it for you to create the string for the query. This will look a little more pretty at least.
Otherwise, REF CURSOR's need to go back and forth - I don't know how you can pipe the results of the REF CURSOR in one connection to the query in another without looping through it.

Resources