Last night got a call from my team lead and he asked me to make the list of all the procedures along with the tables and columns used in Oracle.
I got a query to list all the procedures along with tables and dblink but couldn't get column names (along with DML if possible) used in that Procedure :
select DISTINCT OWNER, NAME, referenced_name, referenced_link_name, referenced_type
from dba_dependencies
where OWNER = 'OWNER_NAME';
My required output is as follows:
Owner_Name
Procedure_Name
Referenced_name
Referenced_link
Referenced_type
Column_Name,
dml_type(select/insert/update).
Please help if possible..
columns will be in DBA_TAB_COLUMNS.
as for the SQL statements, this is a bit more difficult, but doable if you have Diagnostics pack licensed; here's the outline (works in 11g or above):
DBA_HIST_ACTIVE_SESS_HISTORY.top_level_sql_id is the SQL id of the calling procedure,
so listing DBA_HIST_ACTIVE_SESS_HISTORY.sql_id for that top_level_sql_id is "all" the SQL from the execution of the procedure.
DBA_HIST_SQL_TEXT can be queried to get the sql text for the sql_id.
If you don't have the Diagnostics Pack, you'd have to instrument v$session for the top_level_sql_id's and sql_id's and the look in v$sql for the text.
In PLSQL I run:
truncate table MyOracleTableName;
commit work;
insert into MyOracleTablename
select a,b,c,trunc(sysdate) as datadate
from AnotherOracleTableName
where there is a ton of nasty criteria
union
select a,b,c,trunc(sysdate) as datadate from AnotherOracleTableName
where there is a ton of different nasty criteria;
commit work;
In PLSQL Developer this inserts one row.
When I run the SQL (without the semi colons and the commit work statements) in SSIS, I get a primary key violation from MyOracleTableName.
I have validated that the truncate from SSIS is committed in Oracle.
When I run the SQL above in PLSQL Developer and replace the union with union all, I see a second row and the insert fails for a PK violation. As it should with a union all allowing the duplicate.
This is currently part of an SSIS 2005 package using MSDAORA where it works just fine. I am now re-writing in SSIS 2008 using Native OLE DB providor for Oracle.
I cannot use MSDAORA in my new environment. Is this a driver issue and is there a work around other than breaking these into multiple statements where the second inserts only what is not already in MyOracleTableName?
Regards.
I figured out the problem after dinner.
The Primary key constraint is a composite key on columns A and B. The Union de-dups on columns a,b,c and the date. In Oracle the trunc(sysdate) returns mm/dd/yyyy. In SSIS the trunc(sysdate) is being parsed out to the second or milisecond. This results in two unique rows (to SQL Server and Microsoft) due to the timestamp, and then attempts to insert duplicate rows where columns a,b, and c are duplicated.
The solution is this:
truncate table MyOracleTableName;
commit work;
insert into MyOracleTablename
select a.*,
trunc(sysdate) as datadate
from(
select a,b,c
from AnotherOracleTableName
where there is a ton of nasty criteria
union
select a,b,c from AnotherOracleTableName
where there is a ton of different nasty criteria) a
commit work;
This allows the union to kill the duplicate and runs the trunc(sysdate) once thereby presenting the single row to my primary key constraint.
Thank you.
I have been using SQL Server 2008 for a short time now and have never used Oracle before. I am able to access an Oracle table through SQL Server with the syntax
select * from [OracleDB1]..[OracleDB1].[Zips]
(where OracleDB1 is the oracle database and Zips is the table I require)
Is it possible to join a SQL Server table with this one in a Table-valued Function? Just using a normal join as I would with SQL Server tables gives an Invalid object name error on the Oracle table.
Can this be done directly (or at all) or is it possible to do this some other way such as table variables?
example query:
select * from dbo.Table1 t INNER JOIN [OracleDB1]..[OracleDB1].[Zips] z where t.zip = z.zip
I was performing the join wrong since I missed the ON clause. I was able to get it to work by declaring a temptable and joining on that.
declare #tempTable table{
ZIP nvarchar(5),
COUNTY nvarchar(10)
}
insert #tempTable select ZIP, COUNTY, from [OracleDB1]..[OracleDB1].[ZIPS]
select * from dbo.Table1 t INNER JOIN #tempTable z on t.ZIP = v.ZIP where t.AdmissionOn >= '08-08-2011' AND t.AdmissionOn <= ''09-08-2011'
This also worked in line as I had in the original question once I added the ON clause but the table variable suits my needs better since it only has to access the Oracle table once and not each comparison.
I'm using Oracle 10g (XE 10.2.0.1.0), and find a behavior that I don't understand:
select *
from employees manager
join employees worker on MANAGER.EMPLOYEE_ID = WORKER.MANAGER_ID
join departments on DEPARTMENTS.manager_id = 108
where
department_id = 100
;
The problem is I think Oracle should have complain about the ambiguity of department_id in the where clause, since it's a column in both the table employees and departments. The fact is in Oracle 10g, it doesn't, and the result shows that it interprets the department_id as the one in departments. However, if I comment out the second join statement (4th line above), Oracle does complain “ORA-00918: column ambiguously defined” as expected.
So, can somebody help to explain how the ambiguity is defined in Oracle 10g? Or perhaps this is a bug in 10g?
BTW: The tables are defined in the default HR schema bundled in the Oracle 10g.
Update: Just found a related post:
Why does Oracle SQL mysteriously resolve ambiguity in one joins and does not in others
I believe it is a bug in Oracle 10g that Oracle chose not to fix. When we were upgrading our applications from 10g to 11gR2, we found a couple of queries that were written "loosely" in respect of ambiguous column names but worked in Oracle 10g. They all stopped working in 11gR2. We contacted Oracle but they pretty much said that the tolerant behavior toward ambiguous column names is a correct behavior for Oracle 10g and the stringent behavior is the correct behavior for 11g.
I think it is, because departments have no alias. Therefore everything without being qualified by an <alias>. is first treated to be from departments.
So I also think when you give departments an alias you should get the ORA-00918 again. Cannot test here though...
I've heard people referring to this table and was not sure what it was about.
It's a sort of dummy table with a single record used for selecting when you're not actually interested in the data, but instead want the results of some system function in a select statement:
e.g. select sysdate from dual;
See http://www.adp-gmbh.ch/ora/misc/dual.html
As of 23c, Oracle supports select sysdate /* or other value */, without from dual, as has been supported in MySQL for some time already.
It is a dummy table with one element in it. It is useful because Oracle doesn't allow statements like
SELECT 3+4
You can work around this restriction by writing
SELECT 3+4 FROM DUAL
instead.
From Wikipedia
History
The DUAL table was created by Chuck Weiss of Oracle corporation to provide a table for joining in internal views:
I created the DUAL table as an underlying object in the Oracle Data Dictionary. It was never meant to be seen itself, but instead used
inside a view that was expected to be queried. The idea was that you
could do a JOIN to the DUAL table and create two rows in the result
for every one row in your table. Then, by using GROUP BY, the
resulting join could be summarized to show the amount of storage for
the DATA extent and for the INDEX extent(s). The name, DUAL, seemed
apt for the process of creating a pair of rows from just one. 1
It may not be obvious from the above, but the original DUAL table had two rows in it (hence its name). Nowadays it only has one row.
Optimization
DUAL was originally a table and the database engine would perform disk IO on the table when selecting from DUAL. This disk IO was usually logical IO (not involving physical disk access) as the disk blocks were usually already cached in memory. This resulted in a large amount of logical IO against the DUAL table.
Later versions of the Oracle database have been optimized and the database no longer performs physical or logical IO on the DUAL table even though the DUAL table still actually exists.
I think this wikipedia article may help clarify.
http://en.wikipedia.org/wiki/DUAL_table
The DUAL table is a special one-row
table present by default in all Oracle
database installations. It is suitable
for use in selecting a pseudocolumn
such as SYSDATE or USER The table has
a single VARCHAR2(1) column called
DUMMY that has a value of "X"
It's the special table in Oracle. I often use it for calculations or checking system variables. For example:
Select 2*4 from dual prints out the result of the calculation
Select sysdate from dual prints the server current date.
A utility table in Oracle with only 1 row and 1 column. It is used to perform a number of arithmetic operations and can be used generally where one needs to generate a known output.
SELECT * FROM dual;
will give a single row, with a single column named "DUMMY" and a value of "X" as shown here:
DUMMY
-----
X
Kind of a pseudo table you can run commands against and get back results, such as sysdate. Also helps you to check if Oracle is up and check sql syntax, etc.
The DUAL table is a special one-row table present by default in all Oracle database installations. It is suitable for use in selecting a pseudocolumn such as SYSDATE or USER
The table has a single VARCHAR2(1) column called DUMMY that has a value of "X"
You can read all about it in http://en.wikipedia.org/wiki/DUAL_table
DUAL is necessary in PL/SQL development for using functions that are only available in SQL
e.g.
DECLARE
x XMLTYPE;
BEGIN
SELECT xmlelement("hhh", 'stuff')
INTO x
FROM dual;
END;
More Facts about the DUAL....
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1562813956388
Thrilling experiments done here, and more thrilling explanations by Tom
DUAL we mainly used for getting the next number from the sequences.
Syntax : SELECT 'sequence_name'.NEXTVAL FROM DUAL
This will return the one row one column value(NEXTVAL column name).
another situation which requires select ... from dual is when we want to retrieve the code (data definition) for different database objects (like TABLE, FUNCTION, TRIGGER, PACKAGE), using the built in DBMS_METADATA.GET_DDL function:
select DBMS_METADATA.GET_DDL('TABLE','<table_name>') from DUAL;
select DBMS_METADATA.GET_DDL('FUNCTION','<function_name>') from DUAL;
in is true that nowadays the IDEs do offer the capability to view the DDL of a table, but in simpler environments like SQL Plus this can be really handy.
EDIT
a more general situation: basically, when we need to use any PL/SQL procedure inside a standard SQL statement, or when we want to call a procedure from the command line:
select my_function(<input_params>) from dual;
both recipes are taken from the book 'Oracle PL/SQL Recipes' by Josh Juneau and Matt Arena
The DUAL is special one row, one column table present by default in all Oracle databases. The owner of DUAL is SYS.
DUAL is a table automatically created by Oracle Database along with the data functions. It is always used to get the operating systems functions(like date, time, arithmetic expression., etc.)
SELECT SYSDATE from dual;
It's a object to put in the from that return 1 empty row. For example:
select 1 from dual;
returns 1
select 21+44 from dual;
returns 65
select [sequence].nextval from dual;
returns the next value from the sequence.