oracle: primary key column in a materialized view - oracle

The task is to create a materialized view with the primary key on some unique column, so the materialized view could be replicated to another DB. The problem is that there are no unique columns because I had to join a very large number of tables, so I can not use the IDs from the joined tables, as they are not unique anymore in my materialized view.
First of all I have to create a view, because there are subqueries in the select:
CREATE VIEW V_CONTRACTS
AS
SELECT
ID.NEXTVAL,
C.*
FROM (SELECT <lots of columns>
FROM CONTRACT
<lots of joins>
WHERE <some filters>) C
;
But the error is thrown:
ORA-02287: sequence number not allowed here
Then I will create the materialized view as:
CREATE MATERIALIZED VIEW CONTRACTS
AS
SELECT * FROM V_CONTRACTS;

You could use the ROW_NUMBER analytic function to give you a number column.
CREATE VIEW V_TEST
AS
SELECT
ROW_NUMBER() OVER ( ORDER BY col1 , col2 ) as idx,
C.*
FROM ( SELECT 'A' as col1, 'B' as col2 FROM DUAL
UNION
SELECT 'C' as col1, 'D' as col2 FROM DUAL
UNION
SELECT 'E' as col1, 'F' as col2 FROM DUAL
) C ;
CREATE MATERIALIZED VIEW mv_test
AS
SELECT * FROM V_TEST ;
SELECT * FROM mv_test ;

Related

query to get all tables in a materialized view

Good afternoon friends,
a query is there any way (select * from) to visualize which tables form a materialized view?
ex:
CREATE MATERIALIZED VIEW table_vm
REFRESH COMPLETE ON COMMIT
as
SELECT * FROM table1;
UNION ALL
SELECT * FROM table2;
I would like to output something like this:
view name | table name
table_m | Table 1
table_m | table 2
tabla_m | table 3
....
....
Thank you so much,
I would appreciate any information.
You can use the view DBA_DEPENDENCIES to view any dependencies for an object compiled into the database. Querying that view with the name of your materialized view should list all of the tables as well as any other dependencies the materialized view relies on. REFERENCED_OWNER and REFERENCED_NAME will hold the values of the tables being used by the materialized view.
SELECT *
FROM dba_dependencies
WHERE owner = 'OWNER_OF_MV' AND name = 'TABLE_MV';
One option would be
SQL> create table t1 ( c1 number, c2 varchar2(1) ) ;
Table created.
SQL> create table t2 ( c1 number , c3 varchar2(1) ) ;
Table created.
SQL> create table t3 ( c1 number , c3 varchar2(1) ) ;
Table created.
SQL> create materialized view mv1 refresh complete on demand as
2 select a.c1 , b.c3 as c2, c.c3
3 from t1 a inner join t2 b on a.c1 = b.c1
4 left join t3 c on a.c1 = c.c1 ;
Materialized view created.
SQL> select name as mv, listagg(referenced_name || ' - ' || referenced_type , '|' )
within group ( order by referenced_name ) as list_dep
from dba_dependencies where name='MV1' and name != referenced_name
group by name
MV LIST_DEP
------------------------------ --------------------------------------------------
MV1 T1 - TABLE|T2 - TABLE|T3 - TABLE

How to load the values of three column from one table1 to another table 2 which is having single column in hive?

Could you please help me below query.
Table 1 (Input)had three columns (Credit_date, Debit_date, Payment_date) and
Table 2 (Output) has one column date
The three column values from Table 1 should be available in Table 2.
I tried below query but not working.
insert into table2
select date
from (
(select credit_date, debit_date, Payment_date from table 1) as date)t;
Could you please guide.
Try doing a union all:
insert into table2
select * from (
select credit_date as date from table1
union all
select debit_date as date from table1
union all
select payment_date as date from table1
) t

Inserting from a SELECT but changing one column in the middle?

Wondering if there is a way to insert a row into a table from another, with exception of one column in the middle without specifying all the column name? I have 128 columns in the table.
I created a view to store the original records.
CREATE VIEW V_TXN_STG AS
SELECT * FROM TXN_STG;
In table TXN_STG, only one column BRN_CODE is changing.
Something like this doesn't work, because the column is not on the last, but somewhere middle of table structure.
INSERT INTO TXN_STG
SELECT v.*, 'BRN-001' AS BRN_CODE
FROM V_TXN_STG v;
I don't believe that this is possible without explicitly specifying the columns in your select.
first you have to get the columns:
SELECT listagg(column_name, ',') within group (order by column_name) columns
FROM all_tab_columns
WHERE table_name = 'AAA' --Table to insert too
and column_name <> 'B' -- column name you want to exclude
GROUP BY table_name;
Then insert that result on the first row:
insert into aaa(A,C) -- A,C is my result from above,I have excluded column B
select *
from (select 'a' A,'q' AMOUNT,'c' C from dual union all -- my sample data
select 'a','a','c' from dual union all
select 'a','b','c' from dual union all
select 'a','c','c' from dual union all
select 'a','d','c' from dual )
pivot
(
max(1)
for (AMOUNT) -- the column you want to remove from the sample data
IN ()
)
where 1=1
order by A;

Copy rows from one table to another, ignoring duplicates on remote

I have two table with the same columns in different databases. Both table have records.i want to insert the records of table2 in table1 but i want to ignore those records which are already in table 1. As well i want to store all ignored records in a new table.
Example:
create table dest
(id number primary key,
col1 varchar2(10));
create table src
(id number,
col1 varchar2(10));
insert into src values(1,'ABC');
insert into src values(2,'GHB');
insert into src values(3,'DUP');
insert into src values(3,'DUP');
commit;
merge into dest
using
(select id,col1 from src) src on(dest.id=src.id)
when not matched then
insert values(src.id,src.col1)
when matched
then update set dest.col1=src.col1;
Error report -
SQL Error: ORA-00001: unique constraint (SCOTT.SYS_C0010807) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
you can use intersect and minus to determine the differences
-- Test Data
-- table1#abc
with data1(id,
val) as
(select 1, 'val1'
from dual
union all
select 2, 'val2'
from dual
union all
select 3, 'val3'
from dual),
-- table2#xyz
data2(id,
val) as
(select 1, 'another val1'
from dual
union all
select 2, 'val2'
from dual
union all
select 4, 'val4'
from dual)
-- Intersection
select 'Intersection', intersection.*
from ((select * from data2) intersect (select * from data1)) intersection
union all
-- data2 not in data1
select 'data2 not in data1', d2.*
from ((select * from data2) minus (select * from data1)) d2
union all
-- data1 not in data2
select 'data1 not in datad', d1.*
from ((select * from data1) minus (select * from data2)) d1;

how do I split a numeric column into two separate columns in Oracle SQL

I am trying to join two tables together but the key in one table is formated like 'xxxxxx' and the key I am trying to join together in the second table is formated like '2222xxxxxx'. Is there a way I can either split the second column into two different columns to make the join, or join on only the last 6 numbers of column 2?
Notes: values are numeric. the '2222' is always the same 4 numbers.
Try this way:
select *
from table1 a
INNER JOIN table2 b
on a.fieldname = substr(b.fieldname, -6)
Here is the documentation for the SUBSTR Function in Oracle.
Know that this is a very bad design for your second table you should consider in separating this values in different columns.
EDIT
This comment from #Boneist "if there were 7 numbers after the first 4, not just 6?"
To fix this you should use: substr(b.fieldname, 5)
To separate that column on a select statement either you create a new column and update it values with the given substr or just add it in the select command.
On the select command:
select fielda, fieldb,
substr(b.fieldname, 1, 4) firstPartOfField,
substr(b.fieldname, 5) secondPartOfField
from tableb
To create another column it would be
alter table tableb add column newField number(6);
update tableb
set oldField = substr(b.fieldname,1,4),
newField = substr(b.fieldname,5);
I would suggest a slightly different approach:
If your column has varchar/char data type:
drop table tab1;
drop table tab2;
create table tab1(col char(30));
create table tab2(col char(30));
insert into tab1
select lpad(to_char(level), 6, '0') as val
from dual connect by level <=100 order by level;
insert into tab2
select '2222' || lpad(to_char(level), 6, '0') as val
from dual connect by level <=100 order by level;
create unique index ux_tab1 on tab1(col);
create unique index ux_tab2 on tab2(col);
select tab1.col, tab2.col
from tab1
join tab2
on '2222' || tab1.col = tab2.col;
-- check execution plan
explain plan for
select tab1.col, tab2.col
from tab1
join tab2
on '2222' || tab1.col = tab2.col;
select * from table(dbms_xplan.display);
If your column has number data type:
drop table tab1;
drop table tab2;
create table tab1(col number);
create table tab2(col number);
insert into tab1
select 100000 + level as val
from dual connect by level <=100 order by level;
insert into tab2
select 2222100000 + level as val
from dual connect by level <=100 order by level;
create unique index ux_tab1 on tab1(col);
create unique index ux_tab2 on tab2(col);
select tab1.col, tab2.col
from tab1
join tab2
on 2222000000 + tab1.col = tab2.col;
-- check execution plan
explain plan for
select tab1.col, tab2.col
from tab1
join tab2
on 2222000000 + tab1.col = tab2.col;
select * from table(dbms_xplan.display);
Using this approach Oracle will be able to use indexes for joining !

Resources