Join between a sqlsever table and an oracle table - oracle

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.

Related

Query working in native Oracle sql but not through odbc. Alias from subquery is an invalid identifier

A collegue needs to work with this data in Excel. I wrote the query below. It runs fine when I run it from sql developer. But when I want to use it in Microsoft Query which apparently uses ODBC to connect to the Oracle database, I get an error that says that the identifier "due" is invalid.
But how can I name the sum from the subquery in the select part of the sql?
SELECT cl.clid, cl.cl_name, s.due, con.oid, con.contract_status
FROM clientinfo cl
LEFT OUTER JOIN
(SELECT clid, sum(dueamount) as due
from account GROUP BY clid) s
ON s.clid = cl.clid
LEFT OUTER JOIN contract con
ON con.clid = cl.clid
ORDER BY cl.clid
I translated the names into english so that the query makes a bit more sense to you. I want to show the client id and their names along with the due amount and an object number with the status of the contract.
Create a view in the Oracle DB and let your colleague query that view through ODBC.

Using Date in Where Clause

I am trying to place a date in a where clause. I want to update all rows in which the date column is before or after a certain date. How do I specify that I only want to update these columns. Here is the coding that I have so far (not including specific column names):
update table1
set column1 = value
where (select date from table2) < date;
Am I on the right track?
Also, could someone please explain the difference between SQL and PL/SQL. I am taking a class in PL/SQL at the moment. Whenever I post a question on this forum I say that I have a question in PL/SQL, but the people who answer my question say that a certain function - update/if/case/etc. - is a SQL statement and not a PL/SQL statement. What is the difference?
-Neil
Your update statement
update table1
set column1 = value
where (select date from table2) < date;
is correct and it will work but only if the inner query (select date from table2) returns a single row. If you are trying to compare to specific date you don't need the inner query, for example:
update table1
set column1 = value
where to_date('01/02/2012', 'DD/MM/YY') < date;
You can adjust date format mask to whatever format of data you prefer. to_date will convert from char to date type, and to_char will do the opposite.
SQL is a standardized query language that is supported by all compliant relational databases (with some proprietary extensions sometimes). SQL is not a programming language. PL/SQL is a procedural programming language that is supported on Oracle only (Postgres has similar syntax). PL/SQL is SQL + regular programming language features like conditional statements (if/else), loops (for), functions and procedures and such. PL/SQL is used whenever it's too difficult or impossible to get some data using SQL solely.
As Aleksey mentioned, your query is correct but you need to either [1] set conditions around the sub-SQL to only return ONE record or [2] make sure the data in tabl2 only has ONE record when it runs.
ie
If you have to refer to data from another table in your WHERE clause consider explicit joins (example in SQL Server) ...
update t1
set t1.column1 = value -- <-- some arbitary value here I assume?
from table1 t1
inner join table2 t2
on (t2.key = t1.key) -- you need to specify the primary keys of the tables here
where t2.date < t1.date
That way you are not assuming table2 has only one record. It can have many records as long as they relate to table1 via their keys/indexes and the WHERE clause simply makes sure you only UPDATE based on data from table2 that has a date LESS THAN the date in table1.

Why does an Oracle Union create a duplicate in SSIS?

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.

Oracle--Error(Refereence to object_id)

SELECT object_id from dbname.tablename
This query has to be executed against oracle 11g.I get errors when i execute this.
I do a migration from sybase to oracle and in oracle this query fails.
What could be the problem. Please suggest a solution
"What could be the problem."
All sorts of things. Since you failed to state what errors you're getting, we can only guess, e.g.:
Table not found
No SELECT privilege on table
dbname not a valid schema
object_id not a column in the table
Not connected to a running oracle instance
Trying to run the statement in an environment that doesn't understand SQL
etc, etc, ...
If all you want is to check that the table exists, you could do this:
SELECT 1 FROM dba_tables WHERE owner = 'DBNAME' AND table_name = 'TABLENAME';
If you want to check that you can query the table, you could do this:
SELECT 1 FROM schemaname.tablename WHERE 1=0;
If you want to check if the table has any rows, you could do this:
SELECT 1 FROM schemaname.tablename WHERE ROWNUM <= 1;
What you will do with the result. If you only want a unique id for a row, yo can user SELECT ROWID FROM dbname.tablename!

Why the Select * FROM Table where ID NOT IN ( list of int ids) query is slow in sql server ce?

well this problem is general in sql server ce
i have indexes on all the the fields.
also the same query but with ID IN ( list of int ids) is pretty fast.
i tried to change the query to OUTER Join but this just make it worse.
so any hints on why this happen and how to fix this problem?
That's because the index is not really helpful for that kind of query, so the database has to do a full table scan. If the query is (for some reason) slower than a simple "SELECT * FROM TABLE", do that instead and filter the unwanted IDs in the program.
EDIT: by your comment, I recognize you use a subquery instead of a list. Because of that, there are three possible ways to do the same (hopefully one of them is faster):
Original statement:
select * from mytable where id not in (select id from othertable);
Alternative 1:
select * from mytable where not exists
(select 1 from othertable where mytable.id=othertable.id);
Alternative 2:
select * from mytable
minus
select mytable.* from mytable in join othertable on mytable.id=othertable.id;
Alternative 3: (ugly and hard to understand, but if everything else fails...)
select * from mytable
left outer join othertable on (mytable.id=othertable.id)
where othertable.id is null;
This is not a problem in SQL Server CE, but overall database.
The OPERATION IN is sargable and NOT IN is nonsargable.
What this mean ?
Search ARGument Able, thies mean that DBMS engine can take advantage of using index, for Non Search ARGument Ablee the index can't be used.
The solution might be using filter statement to remove those IDs
More in SQL Performance Tuning by Peter Gulutzan.
ammoQ is right, index does not help much with your query. Depending on distribution of values in your ID column you could optimise the query by specifying which IDs to select rather than not to select. If you end up requesting say more than ~25% of the table index will not be used anyway though because for nonclustered indexed (which is the only type of indexes which SQL CE supports if memory serves) it would be cheaper to scan the table. Otherwise (if the query is actually selective) you could re-write query with ID ranges to select ('union all' may work better than 'or' to combine ranges if SQL CE supports 'union all', not sure)

Resources