How to run this query on Oracle Developer? - sql

I have this query as a part of powershell script and it runs ok on Sql server but fails on Oracle
select case when OBJECT_ID (N'INTERFACE_DEFINITION', N'U') is null then 0 else 1 end
Here is error: ORA-00923: FROM keyword not found where expected
Is there some change required to make this work?
Thanks.

select case when 'a' > 'b' then 0 else 1 end
from DUAL;
The DUAL table is present in every Oracle database. This special table
contains just one column. The column is named DUMMY, and it has a
datatype of VARCHAR2(1). The DUAL table contains only one row. That
row has a value in DUMMY of ‘X’.
The purpose of DUAL is simple—to have
something to run a SELECT statement against when you don’t wish to
retrieve any data in particular but instead simply wish to run a
SELECT statement to get some other task accomplished.
Verifying that an object exists:
OBJECT_ID (N'INTERFACE_DEFINITION', N'U')
In Oracle you may use this query:
select count(*) from all_objects where object_name = 'INTERFACE_DEFINITION';
all_objects doesn't necessarily shows you all the objects in the database. It only shows you the objects on which a current user has any priviledges.

Related

Optimize view that dynamically choose a table or another

So the problem is that I have three huge table with same structure, and I need to show the results of one of them depending on result from another query.
So my order table looks like that:
code order
A 0
B 2
C 1
And I need to retrieve data from t_results
My approach (which is working) looks like this:
select *
from t_results_a
where 'A' in (
select code
from t_order
where order = 0
)
UNION ALL
select *
from t_results_b
where 'B' in (
select code
from t_order
where order = 0
)
UNION ALL
select *
from t_results_c
where 'C' in (
select code
from t_order
where order = 0
)
Is there anyway to not scan all three tables, as I am working with Athena so I can't program?
I presume that changing your database schema is not an option.
If it were, you could use one database table and add a CODE column whose value would be either A, B or C.
Basically the result of the SQL query on your ORDER table determines which other database table you need to query. For example, if CODE in table ORDER is A, then you have to query table T_RESULTS_A.
You wrote in your question
I am working with Athena so I can't program
I see that there is both an ODBC driver and a JDBC driver for Athena, so you can program with either .NET or Java. So you could write code that queries the ORDER table and use the result of that query to build another query string to query just the relevant table.
Another thought I had was dynamic SQL. Oracle database supports it. I can create a string containing variables where one variable is the database table name and have Oracle interpret the string as SQL and execute it. I briefly searched the Internet to see whether Athena supports this (as I have no experience with Athena) but found nothing - which doesn't mean to say that it does not exist.

Select from nothing in Oracle without referencing the dual table?

selecting from nothing in Oracle SQL happens while referencing the dual table, like
SELECT sysdate FROM dual;
Now I'd like to have a query that also works for PostgreSQL, but selecting from dual there isn't possible. I know that I can drop the whole FROM part, but then it won't work in Oracle.
I've also tried things like SELECT CURRENT_TIMESTAMP FROM VALUES(1)) V(C);, but Oracle can't do this, either.
So is there a way to select from nowhere without using the dual table in Oracle SQL?
Alternatively, create a table named dual in Postgres, made of 1 row and 1 column
create table dual as (select 1);
and you can use it in Postgres as you would in Oracle
select 'whatever' from dual;
?column?
-----------
whatever
sysdate in Oracle is a built-in function, i.e. not a database table column. You can use any table as long as the query returns precisely one row, e.g.
select sysdate from EMP where rownum < 2
If you have a small table, TABLE_B, with at least one row, you could try selecting a single row from it.
select sysdate from TABLE_B where rownum < 2;
The contents of the table don't matter because you won't be selecting any of its columns.
The below code generates a fake row in both Oracle and Postgres (10+), using the XMLTABLE function. This code is pretty weird but it doesn't require any custom objects.
--Generate a fake row in either Oracle or Postgres.
select *
from xmltable
(
--The expression syntax is different for Oracle and Postgres.
--Oracle can use a literal, Postgres must reference the XML.
--The string '' is null in Oracle but not null in Postgres.
case when '' is null then '1' else '/a' end passing '<a>1</a>'
columns test int path '.'
);
test
----
1

select count(*) from table_name returns error

I am attempting query my oracle database to determine the number of entries in each table. I spooled the result of the following query to a sql file :
select 'select count(*) '||table_name||';' from dba_tables;
This created a sql file of the format
select count(*) from Table_Name1;
select count(*) from Table_Name2;
etc
I then spooled the output of running this sql file, however it only returned a count for some of the tables, for other tables it simply says:
'This table or view does not exist'
How can that be if I've just populated that list of table names automatically from the database?
The end aim of this exercise is to have a file with the number of all fields in each table, then make a change to the program using this database and run the same operation again into a new file and compare the 2 so that I can see which tables change when I make a change to the program.
You forgot to fully qualify the names:
select 'select count(*) '||owner||'.'||table_name||';'
from dba_tables;
In case you have tables that have non-standard names, you should throw double quotes in there as well:
select 'select count(*) "'||owner||'"."'||table_name||'";'
from dba_tables;

Getting past an ORA-00904 error with multiple database query

I have some code that runs the same query in 2 different databases.
SELECT
P.MYID,
CASE WHEN
SUBSTR(P.MYID, 1, 1) NOT IN ('W') THEN
'YOUR_ID_IS_NOT_START_WITH_W'
ELSE
(SELECT OTHER_ID FROM PERSON WHERE NUMBER = '2554' )
END AS "ALTERNATE_ID"
FROM
PERS_INFO P
WHERE
P.NUMBER = '2554'
OTHER_ID in this example is a column that only exists in the 2nd database. Thats completely fine because the query will only execute in the 1st database when the id DOES NOT start with 'W'. In otherwords, this query will only ever run in the 1st database, when the MYID does not start with 'W' and will only ever run in the 2nd database when MYID does start with 'W'.
So the query would work in both databases, however, the query fails with an ORA-00904 in the first database because it says OTHER_ID is not legal in the first database (which is true, but i dont care). how do i force oracle to run the query anyways or work around this?
You could create a function in both databases to get the OTHER_ID value. It would just return null in your first database.
For example, in the first database:
create or replace function f_get_other_id(for_no in varchar2) return varchar2 is
begin
return null;
end;
In the second database:
create or replace function f_get_other_id(for_no in varchar2) return varchar2 is
v_other_id varchar2(100);
begin
select other_id into v_other_id from person where number = for_no;
return other_id;
end;
Then, your query can be:
select p.myid,
case
when substr(p.myid, 1, 1) not in ('W') then 'YOUR_ID_IS_NOT_START_WITH_W'
else f_get_other_id('2554')
end as "ALTERNATE_ID"
from pers_info p
where p.number = '2554'
Have you heard about the EXECUTE_IMMEDIATE (http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm) command or about DBMS_SQL (see http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sql.htm)?
If you are working with scripts on various databases that have different tables definition, this might be the solution for you, though this requires PL/SQL.
I'm not sure what the problem would be with adding this column to the database that it is currently absent from, but adding it seems like a pretty low effort and low risk exercise, and would permanently solve this kind of problem.
Probably you need to add another CASE after else checking the database name. Case db_name = db_name1 then your other_id query else some other query lk select 1 from dual... You can get db_name from v$database view.

Select a column that potentially doesn't exist in Oracle dictionary views

I want to create a backwards compatible query on SYS.ALL_ARGUMENTS. In Oracle 11g, the useful ALL_ARGUMENTS.DEFAULTED column was added. Now if I run this query against Oracle 10g:
SELECT defaulted FROM all_arguments
I get an error, of course.
ORA-00904: "SYS"."ALL_ARGUMENTS"."DEFAULTED": invalid identifier
What I'd like to do is this:
SELECT CASE WHEN column_exists("defaulted")
THEN defaulted
ELSE 'N'
END
FROM all_arguments
Or even better
SELECT evaluate_column_on_current_row(column_name => "defaulted",
default_if_not_exists => 'N')
FROM all_arguments
Is there some way to do that in a single SQL query, without resorting to PL/SQL? Or should I check the Oracle version first like this:
SELECT count(*)
FROM all_tab_cols
WHERE owner = 'SYS'
AND table_name = 'ALL_ARGUMENTS'
AND column_name = 'DEFAULTED'
A query that references a column that doesn't exist can't generate a valid plan.
You need to choose an approach where the queries submitted are always valid. Be that dynamically generating/executing them, or some other approach.
But if you submit a query to be parsed, and it contains a non existant field on an existant table, the parser will throw it back at you.