comparing timestamp and date in Derby - derby

I need to compare a date and a timestamp in a SELECT query. Normally, this is supported by most other DB platforms(MySQL, MSSQL, Oracle, etc.) but in Derby it throws this error:
Caused by: java.sql.SQLSyntaxErrorException: Comparisons between
'DATE' and 'TIMESTAMP' are not supported. Types must be comparable.
String types must also have matching collation. If collation does not
match, a possible solution is to cast operands to force them to the
default collation (e.g. SELECT tablename FROM sys.systables WHERE
CAST(tablename AS VARCHAR(128)) = 'T1')
I don't want to use CASTs because I cannot change the SQL query. Is this a bug from Derby that will get fixed sometime? I'm currently using Derby 10.8.2.2.
Thanks!

If you are connecting from a java program you can get specific parts of a Timestamp using various getxxx() methods (these are actually inherited from Java.util.date)
See the docs http://docs.oracle.com/javase/7/docs/api/java/util/Date.html
and check the getDate(), getDay() getHour().... methods

Perhaps you can define a VIEW on one of the tables, and include the CAST in the VIEW. That way, you don't have to change the actual query; it will go against the view, and thus include the cast in that way.

Related

Oracle generated column aliases different on two DB's

We have a legacy application we cannot modify that connects to Oracle 11g and at some point runs a query and returns a result. The application however is using the "generated" column name from Oracle to read the result.
Consider the following query:
select nvl(1,0.0) from DUAL;
As this query does not specify an alias, the generated column name would be "nvl(1,0.0)"
However on another server the generated column name is "nvl(1,0)" (notice 0 and not 0.0) and the application fails.
Is there a configuration that can be changed for Oracle? I've searched for formatting and locale configurations and they are equal on both servers.
Any help would be appreciated
It turns out there's a parameter called cursor_sharing that was set to FORCE instead of EXACT
select nvl(1,0.0) from DUAL;
The query above returns the following depending on the value of the parameter:
FORCE=NVL(1,0)
EXACT=NVL(1,0.0)

JDBC Error in insert with DB2 (works with Sql Server)

I use in a Java Application JDBC to query the DBMS. The application works correctly with Sql Server but I get this error in DB2 during one insert:
com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=1, DRIVER=3.63.75
The insert is made using the ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE.
My query is a plain select of the table, then I declare my PreparedStatement, passing the parameters and afterwards with the ResultSet I do first the moveToInsertRow() and then the insertRow().
Do you know if there are any problems with this approach using DB2?
As I told you before the same code works correctly with Sql Server.
SQL Code -302 on DB2 means:
THE VALUE OF INPUT VARIABLE OR PARAMETER NUMBER position-number IS INVALID OR TOO LARGE FOR THE TARGET COLUMN OR THE TARGET VALUE
So it seems like you are trying to insert a value into a column which is too large or too short (e.g. Hello World into a varchar(5)). Probably the column has a different length in DB2 and sql-server or you are inserting different values.
Probably too late to add to this thread.. but someone else might find it useful
Got the same SQL Exception when trying to do a SELECT : didn't realize the property value in WHERE clause was exceeding the limit on the corresponding column
SELECT * FROM <schema>.<table_name> WHERE PropertyName = 'value';
value was a VARCHAR type but exceeded the Length limit
Detailed exception does say it clearly that data integrity was violated: org.springframework.dao.DataIntegrityViolationException
So a good idea would be to do a length check on the value(s) that are being set on the properties before firing any queries to the database.

INSERT SELECT not working

Using Informix 11.7, I'm trying to execute a INSERT SELECT query with jdbc positional parameters in the select statement like this :
INSERT INTO table1(id, code, label)
SELECT ?, ?, ? FROM table2
WHERE ...
Parameters are set like this :
stmt.setString(1, "auniqueid");
stmt.setString(2, "code");
stmt.setString(3, "coollabel");
I get the following error :
Exception in thread "main" java.sql.SQLException: A syntax error has occurred.
When positional parmeters "?" are placed elsewhere it works fine. I have not this problem using PostgreSQL. What's wrong with my query ? I use the Informix JDBC Driver v3.70 JC1.
Thanks for your help.
Are you expecting to get column names specified via the placeholders? If so, you're on a hiding to nothing; you cannot use placeholders for structural elements of a query such as column or table names. They can only ever replace values. If you want dynamic SQL to specify the columns, use dynamic SQL; create a string with the content:
INSERT INTO table1(id, code, label)
SELECT auniqueid, code, coollabel
FROM table2
WHERE ...
and work with that.
If those placeholders were going to be values, then you'd be inserting the same values over and over, once for each row returned by the query, and that normally isn't what you'd want; you'd simply insert one row with a VALUES clause, where placeholders are permitted:
INSERT INTO table1(id, code, label) VALUES(?, ?, ?);
That would work fine.
AFAIK, this behaviour conforms to the SQL standard. If it works differently in PostgreSQL, then PostgreSQL has provided an extension to the standard.
Warning: I have no experience with Informix, answer is based on general observations
When specifying parameters the database will need to know the type of each parameter. If a parameter occurs in the select-list, then there is no way for the database to infer the type of the parameter. Some database might be capable of delaying that decision until it actually receives the parameters, but most database will need to know this at parse time. This is probably the reason why you receive the error.
Some databases - I don't know if this applies to Informix - allow you to cast parameters. So for example:
SELECT CAST(? AS VARCHAR(20)), CAST(? AS VARCHAR(10)), CAST(? AS VARCHAR(5)) FROM ...
In that case the database will be able to infer the parameter types and be able to parse the query correctly.
With this I do assume you are not trying to specify columnnames for the select-list using parameters, as that is not possible.

ORA-12704: Unable to convert character data

I am trying to perform SET operations in Oracle across remote databases.
I am using the MINUS operator.
My query looks something like this.
SELECT NAME FROM localdb MINUS SELECT NAME from remotedb#dblink
This is throwing up a ORA-12704 error. I understand this warrants some kind of conversion or a NLS Setting.
What should I try next?
The two name columns are stored in different characters sets. This could be because of their type definitions, or it could be because the two databases are using different character sets.
You might be able to get around this by explicitly converting the field from the remote database to the character set of the local one. Try this:
SELECT NAME FROM localdb MINUS SELECT TO_CHAR(NAME) from remotedb#dblink
It seams the types of NAME column in those 2 tables are different.
Make sure the NAME column in the remotedb table is exactly the same type as the NAME in localdb table. It is mandatory when you use a MINUS operator.

Oracle10 and JDBC: how to make CHAR ignore trailing spaces at comparision?

I have a query that has
... WHERE PRT_STATUS='ONT' ...
The prt_status field is defined as CHAR(5) though. So it's always padded with spaces. The query matches nothing as the result. To make this query work I have to do
... WHERE rtrim(PRT_STATUS)='ONT'
which does work.
That's annoying.
At the same time, a couple of pure-java DBMS clients (Oracle SQLDeveloper and AquaStudio) I have do NOT have a problem with the first query, they return the correct result. TOAD has no problem either.
I presume they simply put the connection into some compatibility mode (e.g. ANSI), so the Oracle knows that CHAR(5) expected to be compared with no respect to trailing characters.
How can I do it with Connection objects I get in my application?
UPDATE I cannot change the database schema.
SOLUTION It was indeed the way Oracle compares fields with passed in parameters.
When bind is done, the string is passed via PreparedStatement.setString(), which sets type to VARCHAR, and thus Oracle uses unpadded comparision -- and fails.
I tried to use setObject(n,str,Types.CHAR). Fails. Decompilation shows that Oracle ignores CHAR and passes it in as a VARCHAR again.
The variant that finally works is
setObject(n,str,OracleTypes.FIXED_CHAR);
It makes the code not portable though.
The UI clients succeed for a different reason -- they use character literals, not binding. When I type PRT_STATUS='ONT', 'ONT' is a literal, and as such compared using padded way.
Note that Oracle compares CHAR values using blank-padded comparison semantics.
From Datatype Comparison Rules,
Oracle uses blank-padded comparison
semantics only when both values in the
comparison are either expressions of
datatype CHAR, NCHAR, text literals,
or values returned by the USER
function.
In your example, is 'ONT' passed as a bind parameter, or is it built into the query textually, as you illustrated? If a bind parameter, then make sure that it is bound as type CHAR. Otherwise, verify the client library version used, as really old versions of Oracle (e.g. v6) will have different comparison semantics for CHAR.
If you cannot change your database table, you can modify your query.
Some alternatives for RTRIM:
.. WHERE PRT_STATUS like 'ONT%' ...
.. WHERE PRT_STATUS = 'ONT ' ... -- 2 white spaces behind T
.. WHERE PRT_STATUS = rpad('ONT',5,' ') ...
I would change CHAR(5) column into varchar2(5) in db.
You can use cast to char operation in your query:
... WHERE PRT_STATUS=cast('ONT' as char(5))
Or in more generic JDBC way:
... WHERE PRT_STATUS=cast(? as char(5))
And then in your JDBC code do use statement.setString(1, "ONT");

Resources