Differing results for same select query in JDBC vs. SQL*Plus / Toad - jdbc

I have the following (example) query that I'm trying to run
SELECT some_field
FROM MY_VIEW
WHERE date_field >= TO_DATE('2011-06-22', 'yyyy-mm-dd')
When I run this in SQL*Plus, I get a set of results, when I try through JDBC (using java.sql.Statement) I get the following error: java.sql.SQLException: ORA-01722: invalid number.
To make it even stranger, the following code works through the JDBC:
select field_1
FROM MY_VIEW v1
WHERE field_2 != 'some value'
AND not exists (
SELECT field_1
FROM MY_VIEW v2
WHERE v1.field_1 = v2.field_1
and t1.timestamp < t2.timestamp
)
But the code below (which still works in SQL*Plus) doesn't (same ORA-01722 error):
select field_1
FROM MY_VIEW v1
WHERE field_2 != 'some value'
AND not exists (
SELECT field_1
FROM MY_VIEW v2
WHERE v1.field_1 = v2.field_1
and v2.field_2 = 'some value' -- Does not work with this line (same value as above)
and v1.timestamp < v2.timestamp
)
I'm running Java 6, connecting to Oracle 10g, and using the ojdbc14.jar. I think it's important to note that the view being queried (MY_VIEW) is a fairly complicated thing, including more then one field being casted from varchar to numeric. My current suspicion is that Oracle is creating a different, unworkable, execution plan for the jdbc query then for the SQL*Plus.
Any suggestions on what I should do from here?
Thanks.

Related

global temporary table hibernate

I'm trying to replace a giant IN clause (hundreds of values) with a JOIN for performance reasons, so I created a global temp table (Oracle) hoping that may be a viable alternative:
CREATE GLOBAL TEMPORARY TABLE TMP_USER_GUID (
user_guid varchar(20)
)
ON COMMIT DELETE ROWS
When I run my sql manually, it works fine:
INSERT ALL
INTO ent.tmp_usr_guid VALUES ('00JD49W7IJ93ZU5MBWBQ')
-- as many INTO statements as I would have IN parameters
SELECT * FROM DUAL;
SELECT u.guid, u.first_name, u.last_name, ...
FROM usr u
JOIN ...
JOIN ...
JOIN tmp_usr_guid tug ON u.guid = tug.usr_guid
When I try running it as a native sql statement using Hibernate (5.2.12.FINAL) it throws:
org.hibernate.QueryException: unexpected char: ';' [INSERT ALL INTO
ent.tmp_usr_guid VALUES ('00JD49W7IJ93ZU5MBWBQ') SELECT * FROM DUAL;
SELECT u.guid,
Any thoughts on the correct approach to take?

Oracle CLOB column and LAG

I'm facing a problem when I try to use LAG function on CLOB column.
So let's assume we have a table
create table test (
id number primary key,
not_clob varchar2(255),
this_is_clob clob
);
insert into test values (1, 'test1', to_clob('clob1'));
insert into test values (2, 'test2', to_clob('clob2'));
DECLARE
x CLOB := 'C';
BEGIN
FOR i in 1..32767
LOOP
x := x||'C';
END LOOP;
INSERT INTO test(id,not_clob,this_is_clob) values(3,'test3',x);
END;
/
commit;
Now let's do a select using non-clob columns
select id, lag(not_clob) over (order by id) from test;
It works fine as expected, but when I try the same with clob column
select id, lag(this_is_clob) over (order by id) from test;
I get
ORA-00932: inconsistent datatypes: expected - got CLOB
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 1 Column: 16
Can you tell me what's the solution of this problem as I couldn't find anything on that.
The documentation says the argument for any analytic function can be any datatype but it seems unrestricted CLOB is not supported.
However, there is a workaround:
select id, lag(dbms_lob.substr(this_is_clob, 4000, 1)) over (order by id)
from test;
This is not the whole CLOB but 4k should be good enough in many cases.
I'm still wondering what is the proper way to overcome the problem
Is upgrading to 12c an option? The problem is nothing to do with CLOB as such, it's the fact that Oracle has a hard limit for strings in SQL of 4000 characters. In 12c we have the option to use extended data types (providing we can persuade our DBAs to turn it on!). Find out more.
Some of the features may not work properly in SQL when using CLOBs(like DISTINCT , ORDER BY GROUP BY etc. Looks like LAG is also one of them but, I couldn't find anywhere in docs.
If your values in the CLOB columns are always less than 4000 characters, you may use TO_CHAR
select id, lag( TO_CHAR(this_is_clob)) over (order by id) from test;
OR
convert it into an equivalent SELF JOIN ( may not be as efficient as LAG )
SELECT a.id,
b.this_is_clob AS lagging
FROM test a
LEFT JOIN test b ON b.id < a.id;
Demo
I know this is an old question, but I think I found an answer which eliminates the need to restrict the CLOB length and wanted to share it. Utilizing CTE and recursive subqueries, we can replicate the lag functionality with CLOB columns.
First, let's take a look at my "original" query:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
)
SELECT tt.order_by_col,
tt.clob_col,
LAG(tt.clob_col) OVER (ORDER BY tt.order_by_col)
FROM test_table tt;
As expected, I get the following error:
ORA-00932: inconsistent datatypes: expected - got CLOB
Now, lets look at the modified query:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
),
initial_pull AS
(
SELECT tt.order_by_col,
LAG(tt.order_by_col) OVER (ORDER BY tt.order_by_col) AS PREV_ROW,
tt.clob_col
FROM test_table tt
),
recursive_subquery (order_by_col, prev_row, clob_col, prev_clob_col) AS
(
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, NULL
FROM initial_pull ip
WHERE ip.prev_row IS NULL
UNION ALL
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, rs.clob_col
FROM initial_pull ip
INNER JOIN recursive_subquery rs ON ip.prev_row = rs.order_by_col
)
SELECT rs.order_by_col, rs.clob_col, rs.prev_clob_col
FROM recursive_subquery rs;
So here is how it works.
I create the TEST_TABLE, this really is only for the example as you should already have this table somewhere in your schema.
I create a CTE of the data I want to pull, plus a LAG function on the primary key (or a unique column) in the table partitioned and ordered in the same way I would have in my original query.
Create a recursive subquery using the initial row as the root and descending row by row joining on the lagged column. Returning both the CLOB column from the current row and the CLOB column from its parent row.

datastage error - odbc function "SQLNumResultCols"

I am trying to select table from an oracle database using datastage.
In the ODBC Connector, If i do
select *
from Table_Name
I get this error -
'ODBC function "SQLNumResultCols" reportted: STATE=102:Native Error
Code = 0: Msg = [IBM(DataDirect OEM)][ODBC 20101 driver] 251'.
However if i use -
select cast(colA as varchar(50) as A,
cast(colB as varchar(50) as B
instead of
select *
from table_name
it works just fine. The data type of these columns is NVARCHAR2.
Is there a way to directly get it from
select *
from table_name
(there are about 20 columns in each of these tables)
Found a fix. Changed nvarchar parameter in odbc file

SELECT a table from oracle data dictionary

I am new to SQL and recently installed Oracle 11g. I read the post here on selecting all tables from user_tables. I'm trying to select a specific table and following some of the suggestions in the post does not appear to work.
The following executes fine and returns all tables available to me including a table named faculty_t:
select * from user_tables;
select * from dba_tables;
select * from all_tables;
desc faculty_t;
But I get error when I do the following:
select * from user_tables where table_name = FACULTY_T;
The first set of statements confirm that I do have a table named faculty_t. However, trying to select this table from user_tables, all_tables, or dba_tables does not appear to work for me right now. The error message reads something like:
ORA-00904: "FACULTY_T": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 208 Column: 8
Any thoughts? Thanks!
String literals in SQL are wrapped in '. So:
select * from user_tables where table_name = 'FACULTY_T';
When you did a desc faculty_t, the SQL engine knew that a table name was expected at that spot (the syntax expects a table name there). But in your select query, sql is just looking for the value of a column that happens to have a string data type, so you need to use the ' for a string literal.

Oracle identity column and insert into select

Oracle 12 introduced nice feature (which should have been there long ago btw!) - identity columns. So here's a script:
CREATE TABLE test (
a INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
b VARCHAR2(10)
);
-- Ok
INSERT INTO test (b) VALUES ('x');
-- Ok
INSERT INTO test (b)
SELECT 'y' FROM dual;
-- Fails
INSERT INTO test (b)
SELECT 'z' FROM dual UNION ALL SELECT 'zz' FROM DUAL;
First two inserts run without issues providing values for 'a' of 1 and 2. But the third one fails with ORA-01400: cannot insert NULL into ("DEV"."TEST"."A"). Why did this happen? A bug? Nothing like this is mentioned in the documentation part about identity column restrictions. Or am I just doing something wrong?
I believe the below query works, i havent tested!
INSERT INTO Test (b)
SELECT * FROM
(
SELECT 'z' FROM dual
UNION ALL
SELECT 'zz' FROM dual
);
Not sure, if it helps you any way.
For, GENERATED ALWAYS AS IDENTITY Oracle internally uses a Sequence only. And the options on general Sequence applies on this as well.
NEXTVAL is used to fetch the next available sequence, and obviously it is a pseudocolumn.
The below is from Oracle
You cannot use CURRVAL and NEXTVAL in the following constructs:
A subquery in a DELETE, SELECT, or UPDATE statement
A query of a view or of a materialized view
A SELECT statement with the DISTINCT operator
A SELECT statement with a GROUP BY clause or ORDER BY clause
A SELECT statement that is combined with another SELECT statement with the UNION, INTERSECT, or MINUS set operator
The WHERE clause of a SELECT statement
DEFAULT value of a column in a CREATE TABLE or ALTER TABLE statement
The condition of a CHECK constraint
The subquery and SET operations rule above should answer your Question.
And for the reason for NULL, when pseudocolumn(eg. NEXTVAL) is used with a SET operation or any other rules mentioned above, the output is NULL, as Oracle couldnt extract them in effect with combining multiple selects.
Let us see the below query,
select rownum from dual
union all
select rownum from dual
the result is
ROWNUM
1
1

Resources