Strange behaviour, results from linked DB - oracle

Running this query on Toad
select * from customer#linkedDb
where "CustomerNumber"=1
Gets a single row results, however
select * from customer#linkedDb
where "CustomerNumber"=(select 1 from dual)
Still returns a single row, but almost every column is NULL
Any data-conversion functions or links to other tables cause this same effect. Any ideas?
Trying this on SQL+, I get this:
select "Forename" from customer#linkedDb where "CustomerNumber"=1
Result: Amy
select "Forename" from customer#linkedDb where "CustomerNumber"=(select 1 from dual)
Result: A m y
I am sure this must be some character encoding thing, but I'm stumped.

The problem is converting from nvarchar to varchar...
Select
Cast("Forename" As Varchar(50))
From
customer#linkedDb
Where
"CustomerNumber"=(select 1 from dual)
Doesn't work, because the (select 1 from dual) seems to cause the data to be autocast. What does work is any alteration to the value after casting - which I think may be prompting Oracle to change the order of things
Select
Substr(Cast("Forename" As Varchar(50)),1,50)
From
customer#linkedDb
Where
"CustomerNumber"=(select 1 from dual)
This works. It is an ugly - slightly expensive solution, so I have some workarounds in place - but I thought I would post this as food for thought if anyone else comes across the same problem.

Related

Error with a user defined report in Oracel SQL Developer - Missing IN or OUT parameter at index:: 1

I have created a user defined report within Oracle SQL Developer, with a bind variable.
The report consists of a master_report (style is table), child_report_a containing with a style of 'table' and child_report_b which is the same query, but with the style of 'script'.
I am able to select a cell/row of my master report, and child_report_a data changes accordingly (ie, it returns the cells of the same date I selected.
However, when I try to view this in child_report_b (With the 'script' style) it errors with "Missing IN or OUT parameter at index:: 1".
So the setup is:
tablea
id_pk (number)
name_pk (varchar2)
1
Jack
2
John
3
Amy
tableb
id_fk (number)
start_time(timestamp(6))
1
01-JAN-23 12.00.00.123000000
2
01-JAN-23 13.00.00.123000000
3
02-JAN-23 14.05.00.123000000
User Defined Report:
master_report (Style=Table):
SELECT * FROM tablea
child_report_a (Style=Table) & child_report_b (Style=Script):
SELECT * FROM tablea a INNER JOIN tableb b ON b.id_fk = a.id_pk WHERE trunc(start_time) = trunc(to_timestamp(:STARTTIME)
Any help is appreciated.
EDIT: Included better example of setup.
My goal is to be able to select a row from the master_report, and the child_report_b would return all results which match the date (as currently happens in child_report_a) in the script format.
Welcome to StackOverflow!
The reporting feature is one of my favorites in SQL Developer, so I will try to get you started.
We can't technically answer your question without a fair bit of guessing. We know what's happening on one side of the JOIN, you have a timestamp that you're using TRUNC on.
But we can't tell what is on the other side of the equality predicate in your JOIN.
Here's a working example, see if this helps you.
Parent Query
select trunc(systimestamp) A
from dual
Child Query
select object_name, object_type, last_ddl_time
from user_objects where :A > (trunc(systimestamp) - 30)
And the report -
To debug your report, substitute the bind :STARTTIME with a literal value that is equivalent to what your parent query would return. If that works, so should your report.
Disclaimer: I work for Oracle and am a product manager for SQL Developer.

How do I get the number of rows in each table I have in my oracle database

Can someone tell me how I can get the number of rows in each table in my oracle database? I have found several queries, but none of them worked because I am using oracle 7 and sqlplus 3.2 and basically all what I found didn't work on it. I just need something that would work on sqlplus 3.2.
Required:
Table Name Rows
Table 1 0
Table 2 5
...
Is it possible to do it with something like a loop? Or what exactly should I do?
if SELECT table_name, num_rows from all_tables doesn't give you what you need.
You could use dynamic SQL and counts as Rahul selected.
Run the below to get results which dynamically build a union on all tables, then run the results as it's own query to get final results.
SELECT 'SELECT ' ||t.name || ' as tName, count(*) as Row_Cnt
FROM ' || t.name || ' UNION ALL '
FROM ALL_TABLES t
Just be sure to remove the last union statement on the last query.
Also note: if you don't have access to see the table, it will not come out in this list!
---Updated ------
So if all_tables doesn't exist none of this will work. Since I don't have a oracle 7 instance handy... could you see if SELECT * FROM dictionary returns anything that might produce a list of all the tables? If you find a view or table object use it in place of all_tables above.
I'm reading the docs for oracle 7 now but finding little easily searchable. thus a guess and check method may go faster.

ORA-00907: missing right parenthesis when create varray

In my program there are a lot of situation when i need to get additional information about knowing ids. So i have list of ids, which length may be very long (for example 100000 elements in it).
How i can use this list and transfer in oracle for getting sql without using temp tables?
No i try to use collection:
CREATE TYPE TEST_VARRAY IS VARRAY(5000) OF NUMBER(18);
SELECT G.ID, G.NAME FROM ANY_TABLE G
WHERE G.ID IN
(
SELECT COLUMN_VALUE FROM TABLE(
NEW TEST_VARRAY
(0,1,2,3... and so on ...,995,996,997,998,999)
)
);
there are 1000 numbers. And when I try execute this query the error ORA-00907: missing right parenthesis tips is appeared! But if i delete first 0 (so we have 999 numbers) the sql is executed ok.
What is problem here?
There is a limit in Oracle IN clause.
A comma-delimited list of expressions can contain no more than 1000
expressions. A comma-delimited list of sets of expressions can contain
any number of sets, but each set can contain no more than 1000
expressions.
Read here or here or here
In my opinion, you are misusing collections, at least I am not sure something like you did is good.
As far as I understand you generate this query before run, so what is the problem to do like that?
with ids as (select /*+ materialize */ 1 id from dual union all
select 2 from dual union all
select 3 from dual union all
select 4 from dual union all
/* repeat with the ids you need */
select 9999 from dual)
select *
from yourTable, ids
where yourTable.id = ids.id;
And that's it! Without any limitations, with pure SQL only. I have added materialize hint to ensure it is not performance relevant, but I think it can be skipped.
No temporary tables, no collections, nothing to create and support. Just SQL.
If you will put ids out of with into from clause it will work in any RDBMS (I guess).

Forcing Oracle to do distinct last

I have a quite complicated view (using several layers of views across several database links) which takes a second to return all of it's rows. But, when I ask for distinct rows, it takes considerably more time. I stopped waiting after 4 minutes.
To make my self as clear as possible:
select a, b from compicated_view; -- takes 1 sec (returns 6 rows)
select distinct a, b from compicated_view; -- takes at least 4 minutes
I find that pretty weird, but hey, that's how it is. I guess Oracle messed something up when planing that query. Now, is there a way to force Oracle to first finish the select without distinct, and then do a "select distinct *" on the results? I looked into optimizer hints, but I can't find anything about hinting the order in which distinct is applied (this is first time I'm optimizing a query, obviously :-/).
I'm using Oracle SQl Developer on Oracle 10g EE.
Try:
SELECT DISTINCT A,B FROM (
SELECT A,B FROM COMPLICATED_VIEW
WHERE rownum > 0 );
this forces to materialize the subquery and prevents from view merging/predicate pushing, and likely from changing the original plan of the view.
You may also try NO_MERGE hint:
SELECT /*+ NO_MERGE(alias) */
DISTINCT a,b
FROM (
SELECT a,b FROM COMPLICATED_VIEW
) alias
Since you haven't posted details... try the following:
SELECT DISTINCT A,B
FROM
(SELECT A,B FROM COMPLICATED_VIEW);

Does Oracle's ROWNUM build the whole table before it extract the rows you want?

I need to make a navigation panel that shows only a subset of a possible large result set. This subset is 20 records before and 20 records after the resulted record set. As I navigate the results through the navigation panel, I'll be applying a sliding window design using ROWNUM to get the next subset. My question is does Oracle's ROWNUM build the whole table before it extracts the rows you want? Or is it intelligent enough to only generate the rows I need? I googled and I couldn't find an explanation on this.
The pre-analytic-function method for doing this would be:
select col1, col2 from (
select col1, col2, rownum rn from (
select col1, col2 from the_table order by sort_column
)
where rownum <= 20
)
where rn > 10
The Oracle optimizer will recognize in this case that it only needs to get the top 20 rows to satisfy the inner query. It will likely have to look at all the rows (unless, say, the sort column is indexed in a way that lets it avoid the sort altogether) but it will not need to do a full sort of all the rows.
Your solution will not work (as Bob correctly pointed out) but you can use row_number() to do what you want:
SELECT col1,
col2
FROM (
SELECT col1,
col2,
row_number() over (order by some_column) as rn
FROM your_table
) t
WHERE rn BETWEEN 10 AND 20
Note that this solution has the added benefit that you can order the final result on a different criteria if you want to.
Edit: forgot to answer your initial question:
With the above solution, yes Oracle will have to build the full result in order to find out the correct numbering.
With 11g and above you might improve your query using the query cache.
Concerning the question's title.
See http://www.orafaq.com/wiki/ROWNUM and this in-depth explanation by Tom Kyte.
Concerning the question's goal.
This should be what you're looking for: Paging with Oracle
I don't think your design is quite going to work out as you've planned. Oracle assigns values to ROWNUM in the order that they are produced by the query - the first row produced is assigned ROWNUM=1, the second is assigned ROWNUM=2, etc. Notice that in order to have ROWNUM=21 assigned the query must first return the first twenty rows and thus if you write a query which says
SELECT *
FROM MY_TABLE
WHERE ROWNUM >= 21 AND
ROWNUM <= 40
no rows will be returned because in order for there to be rows with ROWNUM >= 21 the query must first return all the rows with ROWNUM <= 20.
I hope this helps.
It's an old question but you should try this - http://www.inf.unideb.hu/~gabora/pagination/results.html

Resources