check data with multiple 'in' result - oracle

It seems a stupid question, but how to get multiple 'in' result ?
I have 2 tables(tab1,tab2) with the the same 2 columns : table_name and column_name.
I want to check the data in table_name and column_name in tab1 that doest not exists in tab2
this query is wrong but similar to what I want:
select distinct s.table_name , s.column_name from tab1 s where
(S.table_name ,s.column_name) not in ((select table_name from tab2 ,
(select column_name from tab2))

If you want to eliminate rows where pairs (tname, tcolumn) are present in second table then:
select distinct s.table_name, s.column_name
from tab1 s
where (s.table_name, s.column_name)
not in (select table_name, column_name from tab2)
... and if you want to eliminate everything, if tname or tcolumn exists in table2:
select distinct s.table_name, s.column_name
from tab1 s
where s.table_name not in (select table_name from tab2)
and s.column_name not in (select column_name from tab2)

select s.table_name , s.column_name
from tab1 s
MINUS
select t.table_name , t.column_name
from tab2 t;
This should give the data that is only in tab1

There is always the option of using NOT EXISTS:
SELECT s.table_name, s.column_name
FROM tab1 s
WHERE NOT EXISTS ( SELECT 1 FROM tab1 t
WHERE t.table_name = s.table_name
AND t.column_name = s.column_name );

Related

Oracle - How to find where a table is used in a foreign key constraint? [duplicate]

In Oracle SQL Developer, if I'm viewing the information on a table, I can view the constraints, which let me see the foreign keys (and thus which tables are referenced by this table), and I can view the dependencies to see what packages and such reference the table. But I'm not sure how to find which tables reference the table.
For example, say I'm looking at the emp table. There is another table emp_dept which captures which employees work in which departments, which references the emp table through emp_id, the primary key of the emp table. Is there a way (through some UI element in the program, not through SQL) to find that the emp_dept table references the emp table, without me having to know that the emp_dept table exists?
No. There is no such option available from Oracle SQL Developer.
You have to execute a query by hand or use other tool (For instance PLSQL Developer has such option). The following SQL is that one used by PLSQL Developer:
select table_name, constraint_name, status, owner
from all_constraints
where r_owner = :r_owner
and constraint_type = 'R'
and r_constraint_name in
(
select constraint_name from all_constraints
where constraint_type in ('P', 'U')
and table_name = :r_table_name
and owner = :r_owner
)
order by table_name, constraint_name
Where r_owner is the schema, and r_table_name is the table for which you are looking for references. The names are case sensitive
Be careful because on the reports tab of Oracle SQL Developer there is the option "All tables / Dependencies" this is from ALL_DEPENDENCIES which refers to "dependencies between procedures, packages, functions, package bodies, and triggers accessible to the current user, including dependencies on views created without any database links.". Then, this report have no value for your question.
To add this to SQL Developer as an extension do the following:
Save the below code into an xml file (e.g. fk_ref.xml):
<items>
<item type="editor" node="TableNode" vertical="true">
<title><![CDATA[FK References]]></title>
<query>
<sql>
<![CDATA[select a.owner,
a.table_name,
a.constraint_name,
a.status
from all_constraints a
where a.constraint_type = 'R'
and exists(
select 1
from all_constraints
where constraint_name=a.r_constraint_name
and constraint_type in ('P', 'U')
and table_name = :OBJECT_NAME
and owner = :OBJECT_OWNER)
order by table_name, constraint_name]]>
</sql>
</query>
</item>
</items>
Add the extension to SQL Developer:
Tools > Preferences
Database > User Defined Extensions
Click "Add Row" button
In Type choose "EDITOR", Location is where you saved the xml file above
Click "Ok" then restart SQL Developer
Navigate to any table and you should now see an additional tab next to SQL one, labelled FK References, which displays the new FK information.
Reference
http://www.oracle.com/technetwork/issue-archive/2007/07-jul/o47sql-086233.html
Replace [Your TABLE] with emp in the query below
select owner,constraint_name,constraint_type,table_name,r_owner,r_constraint_name
from all_constraints
where constraint_type='R'
and r_constraint_name in (select constraint_name
from all_constraints
where constraint_type in ('P','U')
and table_name='[YOUR TABLE]');
You may be able to query this from the ALL_CONSTRAINTS view:
SELECT table_name
FROM ALL_CONSTRAINTS
WHERE constraint_type = 'R' -- "Referential integrity"
AND r_constraint_name IN
( SELECT constraint_name
FROM ALL_CONSTRAINTS
WHERE table_name = 'EMP'
AND constraint_type IN ('U', 'P') -- "Unique" or "Primary key"
);
SQL Developer 4.1, released in May of 2015, added a Model tab which shows table foreign keys which refer to your table in an Entity Relationship Diagram format.
SELECT DISTINCT table_name,
constraint_name,
column_name,
r_table_name,
position,
constraint_type
FROM (SELECT uc.table_name,
uc.constraint_name,
cols.column_name,
(SELECT table_name
FROM user_constraints
WHERE constraint_name = uc.r_constraint_name) r_table_name,
(SELECT column_name
FROM user_cons_columns
WHERE constraint_name = uc.r_constraint_name
AND position = cols.position) r_column_name,
cols.position,
uc.constraint_type
FROM user_constraints uc
inner join user_cons_columns cols
ON uc.constraint_name = cols.constraint_name
WHERE constraint_type != 'C')
START WITH table_name = '&&tableName'
AND column_name = '&&columnName'
CONNECT BY NOCYCLE PRIOR table_name = r_table_name
AND PRIOR column_name = r_column_name;
This has been in the product for years - although it wasn't in the product in 2011.
But, simply click on the Model page.
Make sure you are on at least version 4.0 (released in 2013) to access this feature.
How about something like this:
SELECT c.constraint_name, c.constraint_type, c2.constraint_name, c2.constraint_type, c2.table_name
FROM dba_constraints c JOIN dba_constraints c2 ON (c.r_constraint_name = c2.constraint_name)
WHERE c.table_name = <TABLE_OF_INTEREST>
AND c.constraint_TYPE = 'R';
To add to the above answer for sql developer plugin, using the below xml will help in getting the column associated with the foreign key.
<items>
<item type="editor" node="TableNode" vertical="true">
<title><![CDATA[FK References]]></title>
<query>
<sql>
<![CDATA[select a.owner,
a.constraint_name,
a.table_name,
b.column_name,
a.status
from all_constraints a
join all_cons_columns b ON b.constraint_name = a.constraint_name
where a.constraint_type = 'R'
and exists(
select 1
from all_constraints
where constraint_name=a.r_constraint_name
and constraint_type in ('P', 'U')
and table_name = :OBJECT_NAME
and owner = :OBJECT_OWNER)
order by table_name, constraint_name]]>
</sql>
</query>
</item>
</items>
I like to do this with a straight SQL query, rather than messing about with the SQL Developer application.
Here's how I just did it. Best to read through this and understand what's going on, so you can tweak it to fit your needs...
WITH all_primary_keys AS (
SELECT constraint_name AS pk_name,
table_name
FROM all_constraints
WHERE owner = USER
AND constraint_type = 'P'
)
SELECT ac.table_name || ' table has a foreign key called ' || upper(ac.constraint_name)
|| ' which references the primary key ' || upper(ac.r_constraint_name) || ' on table ' || apk.table_name AS foreign_keys
FROM all_constraints ac
LEFT JOIN all_primary_keys apk
ON ac.r_constraint_name = apk.pk_name
WHERE ac.owner = USER
AND ac.constraint_type = 'R'
AND ac.table_name = nvl(upper(:table_name), ac.table_name)
ORDER BY ac.table_name, ac.constraint_name
;
Only Replace table_name with your primary table name
select *
from all_constraints
where r_constraint_name in (
select constraint_name
from all_constraints
where table_name='table_name'
);
Replace MY_OWNER_NAME and MY_TABLE_NAME below and you are ready to go RECURSIVELY:
DECLARE
FUNCTION list_all_child_tables_and_constraints(asked_table_name in VARCHAR2, parent_table_name in VARCHAR2)
RETURN VARCHAR2 IS
current_path VARCHAR2(100);
BEGIN
FOR item IN
(SELECT fk.TABLE_NAME, constraint_parent.FK FK1, constraint_child.FK FK2
FROM all_constraints fk, all_constraints pk,
(SELECT acc.CONSTRAINT_NAME, LISTAGG(acc.COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY acc.COLUMN_NAME) AS FK
FROM ALL_CONS_COLUMNS acc
WHERE acc.OWNER = 'MY_OWNER_NAME'
GROUP BY acc.CONSTRAINT_NAME) constraint_parent,
(SELECT acc.CONSTRAINT_NAME, LISTAGG(acc.COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY acc.COLUMN_NAME) AS FK
FROM ALL_CONS_COLUMNS acc
WHERE acc.OWNER = 'MY_OWNER_NAME'
GROUP BY acc.CONSTRAINT_NAME) constraint_child
WHERE pk.owner = fk.r_owner
AND pk.constraint_name = fk.r_constraint_name
AND fk.constraint_type = 'R'
AND pk.table_name = asked_table_name
AND constraint_parent.CONSTRAINT_NAME = fk.CONSTRAINT_NAME
AND constraint_child.CONSTRAINT_NAME = fk.R_CONSTRAINT_NAME
AND pk.owner = 'MY_OWNER_NAME'
AND fk.owner = 'MY_OWNER_NAME')
LOOP
current_path := parent_table_name || ' // ' || item.TABLE_NAME;
DBMS_OUTPUT.PUT_LINE(current_path);
DBMS_OUTPUT.PUT_LINE(' [' || item.FK1 || '] [' || item.FK2 || ']');
DBMS_OUTPUT.PUT_LINE('');
current_path := list_all_child_tables_and_constraints(item.TABLE_NAME, current_path);
END LOOP;
RETURN '-----------FINISHED-----------';
EXCEPTION
WHEN OTHERS THEN
RETURN '-----------FINISHED-----------';
END list_all_child_tables_and_constraints;
BEGIN
DBMS_OUTPUT.PUT_LINE(list_all_child_tables_and_constraints('MY_TABLE_NAME', ''));
END;

Oracle porting natural JOIN

I am reviewing code written by a previous colleague. It uses a "natural join", which I am unfamiliar with and never used.
I would like to change this into JOIN inner, outer, left….. whatever the correct equivalent is, which shows what is actually being joined.
Below is my test case. Any help would be greatly appreciated.
create table holidays(
holiday_date DATE not null,
holiday_name VARCHAR2(20),
constraint holidays_pk primary key (holiday_date),
constraint is_midnight check ( holiday_date = trunc ( holiday_date ) )
);
INSERT into holidays (HOLIDAY_DATE,HOLIDAY_NAME)
WITH dts as (
select to_date('25-NOV-2021 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'Thanksgiving 2021' from dual union all
select to_date('29-NOV-2021 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'Hanukkah 2021' from dual
)
SELECT * from dts;
SELECT constraint_name, constraint_type, column_name
from user_constraints natural join user_cons_columns
where table_name = 'HOLIDAYS';
CONSTRAINT_NAME CONSTRAINT_TYPE COLUMN_NAME
SYS_C0075523509 C HOLIDAY_DATE
IS_MIDNIGHT C HOLIDAY_DATE
HOLIDAYS_PK P HOLIDAY_DATE
In a natural join, Oracle creates an "implicit" join clause based on common column names. If you want to switch to inner join, you'll have to do it yourself.
Natural:
SQL> SELECT constraint_name, constraint_type, column_name
2 from user_constraints natural join user_cons_columns
3 where table_name = 'EMP';
CONSTRAINT_NAME C COLUMN_NAME
------------------------------ - --------------------
SYS_C00105284 C EMPNO
PK_EMP P EMPNO
Which columns are common? Let's see:
SQL> select column_name from all_tab_columns where table_name = 'USER_CONSTRAINTS'
2 intersect
3 select column_name from all_tab_columns where table_name = 'USER_CONS_COLUMNS';
COLUMN_NAME
--------------------
CONSTRAINT_NAME
OWNER
TABLE_NAME
SQL>
Inner:
SQL> SELECT a.constraint_name, a.constraint_type, b.column_name
2 from user_constraints a join user_cons_columns b
3 on a.constraint_name = b.constraint_name
4 and a.owner = b.owner
5 and a.table_name = b.table_name
6 where a.table_name = 'EMP';
CONSTRAINT_NAME C COLUMN_NAME
------------------------------ - --------------------
SYS_C00105284 C EMPNO
PK_EMP P EMPNO
SQL>
OK, but - we know better. As we're querying user_cons... views, they contain data we own so we don't really need an owner. Moreover, constraint names are unique within a single schema, so we don't need table_name either. Therefore, this would do:
SQL> SELECT a.constraint_name, a.constraint_type, b.column_name
2 from user_constraints a join user_cons_columns b on a.constraint_name = b.constraint_name
3 where a.table_name = 'EMP';
CONSTRAINT_NAME C COLUMN_NAME
------------------------------ - --------------------
SYS_C00105284 C EMPNO
PK_EMP P EMPNO
SQL>

ORACLE SQL DEVELOPER-select count(*) from multiple databases

How can I select count(*) from two different databases(call them ZEOTA and SP) having as result:
Zeota SP
88 3
I have tried this:
SELECT COUNT(CONSTRAINT_TYPE) NumberOfPrimaryKeys_Zeota
FROM ALL_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'P'
AND
OWNER = 'ZEOTA';
SELECT COUNT(*) AS NumberOfAttributes_SP
FROM ALL_COL_COMMENTS
WHERE OWNER = 'SP';
But the output shows two separate query results:
Query result 1:
Zeota
88
Query Result 2:
SP
3
However I am trying to do it this way, but having issues:
SELECT
COUNT(DISTINCT TABLE_NAME) AS ZNumOfTables,
COUNT(DISTINCT TABLE_NAME) AS SNumOfTables,
COUNT(DISTINCT TABLE_NAME) AS PNumOfTables
FROM ALL_TAB_COLUMNS
WHERE OWNER = 'SP';
WHERE OWNER = 'ZEOTA';
One option is to use your current queries as CTEs and then just cross join them:
with
t1 as
(select count(constraint_type) num_pk_zeota
from all_constraints
where owner = 'ZEOTA'
and constraint_type = 'PK'
),
t2 as
(select count(*) num_attr_sp
from all_col_comments
where owner = 'SP'
)
select a.num_pk_zeota,
b.num_attr_sp
from t1 a cross join t2 b;
P.S. What you call "databases" are users (schemas) in Oracle.

How to join a count query with another table which has all counts?

I am selecting count of few tables and i have a table named table_counts which has two columns named table_name and table_count. I want to join the result of the query with the table_name column of table_counts table. Please see the example below.
select 'Table 1' as table_name, count(*) as table_count_from table_1
union
select 'Table 2' as table_name, count(*) as table_count_from table_2
union
select 'Table 3' as table_name, count(*) as table_count_from table_3
------------------
++table_counts++++
------------------
table_name table count
Table 1 10
Table 2 20
Table 3 30
I have to join the two things using the table_name. Could someone help me if iam missing few things?
you are searching something like this?
SELECT *
FROM table_counts cnt
LEFT OUTER JOIN (select 'Table 1' as table_name, count(*) as table_count_from table_1
union
select 'Table 2' as table_name, count(*) as table_count_from table_2
union
select 'Table 3' as table_name, count(*) as table_count_from table_3
) subcnt
ON cnt.table_name = subcnt.table_name

get an column name from the table by passing value in oracle

I want a query in oracle to get the column name from the table by passing value.
Means that In most of the case - We write the query like that - select * from table where column = 'value'. But in my case i don't know the column name.
Can any one suggest me.
Thanks in advance...
You can try to build a dynamic query to check all the tables of your DB.
setup:
create table tab1 ( v1 varchar2(100), n1 number, v1b varchar2(100));
create table tab2 ( v2 varchar2(100), n2 number, v2b varchar2(100));
create table tab3 ( v3 varchar2(100), n3 number, v3b varchar2(100));
insert into tab1 values ('Maria', 1, 'aa');
insert into tab1 values ('xx', 2, 'bb');
insert into tab2 values ('yy', 3, 'Maria');
insert into tab2 values ('zz', 3, 'cc');
insert into tab3 values ('WW', 4, 'DD');
build the dynamic query:
select 'select table_name,
matches from (' || listagg(statement, ' UNION ALL ') within group (order by table_name) || ')
where matches > 0'
from (
select 'select ''' || table_name ||
''' as TABLE_NAME, count(1) as MATCHES from ' || table_name || ' WHERE ' ||
listagg(column_name || ' = ''Maria''', ' OR ') within group (order by column_name) as statement,
table_name
from user_tab_columns col
where data_type = 'VARCHAR2'
group by table_name
)
This will return a query, that you can run to check all the tables; in my example, this will build the query (not formatted) :
SELECT table_name, matches
FROM (SELECT 'TAB1' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB1
WHERE V1 = 'Maria'
OR V1B = 'Maria'
UNION ALL
SELECT 'TAB2' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB2
WHERE V2 = 'Maria'
OR V2B = 'Maria'
UNION ALL
SELECT 'TAB3' AS TABLE_NAME, COUNT(1) AS MATCHES
FROM TAB3
WHERE V3 = 'Maria'
OR V3B = 'Maria')
WHERE matches > 0;
Running this query will give:
TABL MATCHES
---- ----------
TAB1 1
TAB2 1
Please notice that I used USER_TAB_COLUMNS, thus searching only in the tables of the login schema; if you want to search in different schemas, you can use ALL_TAB_COLUMNS or DBA_TAB_COLUMNS, depending on what you need and on the privileges of you user; see here for something more.
Also, consider that USER_TAB_COLUMNS will get the colums of tables and views; if you want to limit your search to tables, you can join USER_TAB_COLUMNS(ALL_TAB_COLUMNS, DBA_TAB_COLUMNS) to USER_TABLES (ALL_TABLES, DBA_TABLES) by TABLE_NAME, or TABLE_NAME and OWNER If you decide to use ALL or DBA tables:
SQL> create view vTab1 as select * from tab1;
View created.
SQL> select count(1)
2 from user_tab_columns
3 where table_name = 'VTAB1';
COUNT(1)
----------
3
SQL> select count(1)
2 from user_tab_columns
3 inner join user_tables using(table_name)
4 where table_name = 'VTAB1';
COUNT(1)
----------
0
SQL>
select table_name from user_Tables where table_name = 'bogus';

Resources