DB2 Query issue with Hibernate when checking for values - java

I have this query, using Hibernate 4 and DB2, running a native query:
select * from TABLE1 t where (:param1 is null or t.NAME = :param1)
That throws exception that null is invalid in the context (since SQL becomes select * from TABLE1 t where (null is null or t.NAME = null))
So I tried:
select * from TABLE1 t where (COALESCE(:param1,'!') = '!' or t.NAME = :param1)
That throws exception when I pass value "JUSTIN" -
"THE VALUE OF INPUT VARIABLE OR PARAMETER NUMBER IS INVALID OR TOO LARGE FOR THE TARGET COLUMN OR THE TARGET VALUE"
Which appears to be cause by the fact that DB2 checks the length of ":param1" against "!".
Is there a way in DB2 to pass dynamic parameters?
I'm starting to hate DB2....

Turns out this works with Hibernate:
select * from TABLE1 t where NVL(:param1, t.NAME) = t.NAME;

Related

Spring Boot, JPA / Hibernate: How to execute two raw SELECT queries at once?

When I try to execute two SELECT statements at once as follows below, the logging console returns a runtime error:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT * FROM ...
The Java source code that generates the statements:
#Repository
public class VehicleObjectDbAccess {
#PersistenceContext
EntityManager entityManager;
public List<Object[]> getObjectById(long objectId, long year)
{
int limit = 10;
String tableName = ("i0i"+year)+objectId;
String queryText =
"START TRANSACTION;"
+ "SELECT t.created INTO #startTime FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1;"
+ "SELECT * FROM ObjectTable WHERE created <= (CASE WHEN #startTime IS NULL THEN NOW() ELSE #startTime END) ORDER BY created DESC LIMIT 10;"
+ "COMMIT;";
Query query = this.entityManager.createNativeQuery(queryText);
return query.getResultList();
}
}
Eventually the java source code above translates to
START TRANSACTION;
SELECT t.created INTO #startTime FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1;
SELECT * FROM ObjectTable WHERE created <= (CASE WHEN #startTime IS NULL THEN NOW() ELSE #startTime END) ORDER BY created DESC LIMIT 10;
COMMIT;
I verified that SQL code running it on a MySQL client and it works properly.
How can I execute these two SELECT statements in a single query?
It seems you can divide your compound sql query to two separate SELECT queries:
Query query1 = this.entityManager.createNativeQuery(queryText1);
Query query2 = this.entityManager.createNativeQuery(queryText2);
After that you can get result lists from them and add result lists to one compound List:
List<Object[]> result = new ArrayList<>();
result.addAll(query1.getResultList());
result.addAll(query2.getResultList());
Just use one select statement:
SELECT *, (SELECT t.created FROM ObjectTable as t WHERE t.speed > 30 LIMIT 1) as x FROM ObjectTable WHERE created <=
(CASE WHEN x IS NULL THEN NOW()
ELSE x
END)
ORDER BY created DESC LIMIT 10;
If you don't want to do this for some reason, create a stored procedure that returns a result set and call it...

Unable to solve uncategorized SQLException when calling SQL Server using JDBC

I am using JDBCTemplate to query a SQL server using:
List results = jdbc.query(statement, new ResultDataMapper());
I have tried the statement in PreparedStatementCreator and String formats but neither work. I received the exception below:
SQL state [null]; error code [0]; The statement did not return a result set.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
My sql is:
IF OBJECT_ID('tempdb.dbo.#tempSearch', 'U') IS NOT NULL
DROP TABLE #tempSearch;
CREATE TABLE #tempSearch
(
ID int,
Value VARCHAR(255)
)
INSERT INTO #tempSearch
VALUES(1,'?'),
(2,'?');
with cte as (
select RoleID,','+replace(replace(GroupNames,',',',,'),' ','')+',' GroupNames from UserGroup_Role_Mapping
)
,cte2 as(
select cte.RoleID, replace(cte.GroupNames,','+Value+',','') as GroupNames, s.ID, s.Value
from cte
join #tempSearch s on ID=1
union all
select cte2.RoleID, replace(cte2.GroupNames,','+s.Value+',','') as l, s.ID ,s.Value
from cte2
join #tempSearch s on s.ID=cte2.ID+1
)
SELECT a.Role, a.Sort_Order, a.Parent, a.Parent_ID, a.Parent_URL, a.Child, a.Child_ID,a.Child_URL
FROM NC_View a
WHERE a.Role IN (
Select Name from (
Select distinct RoleID from cte2 where len(GroupNames)=0
) tempRoles
join User_Role
on tempRoles.RoleID = User_Role.ID
)
DROP TABLE #tempSearch
I know the SQL works fine but i just cant get over the hump of calling it from JDBC. I have the Mapper and extractor all done too.
I ran this with a PreparedStatementCreator and String:
when i use PreparedstatementCreator and try to set 2 variables I get index out range errors "com.microsoft.sqlserver.jdbc.SQLServerException: The index 1 is out of range.":
PreparedStatementCreator returnValue = new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
sql.append("("+x +",'" + "?" +"'),"); //when constructing the sql
PreparedStatement statement = con.prepareStatement(sql.toString());
statement.setString(z++, group); //when setting those values
I am not sure why this is? is the syntax incorrect? It seems it is not detecting the set?
from debug i also see:
Unable to translate SQLException with Error code '0'
If I use String straight out i get:
org.springframework.jdbc.UncategorizedSQLException: StatementCallback; uncategorized SQLException for SQL [
SQL FROM ABOVE - I TESTED AND IT WORKS
]; SQL state [null]; error code [0]; The statement did not return a result set.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
I am not sure if the SQL is too complex or what. But also confused how using PreparedStatementCreator it wasnt detecting the ? to set variables... I am running out of ideas. I tried Multiqueries=true too
If I use SET NOCOUNT ON i get a different error:
Unable to solve uncategorized SQLException when calling SQL Server using JDBC
So i am bit confused too. I am not inserting a lot of data so maybe it doesn't matter?
Thanks!

PreparedStatement.executeUpdate() is not working for Oracle

I am using PreparedStatement for executing the update query.
The following is the query:
String callersUpdateQuery = "update W67U999S a set pcrdattim= ? where exists (select b.CRDATTIM, b.RECORDCD, b.CRNODE, b.UNITCD, b.WRKTYPE from W03U999S b where a.PCRDATTIM = ? and a.CCRDATTIM = b.CRDATTIM and a.CRECORDCD = b.RECORDCD and a.CCRNODE = b.CRNODE and a.PRECORDCD = 'F' and a.PCRNODE = '01' and b.WRKTYPE = 'CALLER' and b.UNITCD=? and a.crecordcd='T')";
The below is the java code that should update the records:
preparedStatement = dbConnection.prepareStatement(callersUpdateQuery);
preparedStatement.setString(1,newFolderCrdattim);
preparedStatement.setString(2,crdattim);
preparedStatement.setString(3,businessAreaName.trim());
int j = preparedStatement.executeUpdate();
But preparedStatement.executeUpdate() is not updating the required rows and returning the updated rows count as zero. Weirdly, the same sql query when I execute at the database end, the records are getting updated.
My database is Oracle and the schema of the table that should be updated is below:
Name Null Type
----------- -------- ----------
PCRDATTIM NOT NULL CHAR(26)
PRECORDCD NOT NULL CHAR(1)
PCRNODE NOT NULL CHAR(2)
RECORDTYPE NOT NULL NUMBER(3)
CCRDATTIM NOT NULL CHAR(26)
CRECORDCD NOT NULL CHAR(1)
CCRNODE NOT NULL CHAR(2)
CRDATTIM NOT NULL CHAR(26)
LINKRULE_ID NOT NULL NUMBER(14)
Can anyone guess what's wrong with the code or query?
First, did you check for existence of tuples on the select you're using as condition in where clause?
If there are rows being returned. The issue may be related to the transaction in which you're executing your update statement. Double check for your transaction mode and if it is really being committed.
As a query optimization suggestion I'd change the statement to:
String callersUpdateQuery =
"update W67U999S a
set pcrdattim= ?
where
a.PCRDATTIM = ?
and a.PRECORDCD = 'F'
and a.PCRNODE = '01'
and a.CRECORDCD ='T'
and exists (
select
b.CRDATTIM,
b.RECORDCD,
b.CRNODE,
b.WRKTYPE
from W03U999S b
where
b.CCRDATTIM = a.CRDATTIM
and b.CRECORDCD = a.RECORDCD
and b.CCRNODE = a.CRNODE
and b.WRKTYPE = 'CALLER'
and b.UNITCD=?
)";
That way you will be first reducing the tuples from a then use it to narrow the b tuples only to those that match.
Oracle CHAR type is the culprit here. The columns that I want to update are of type CHAR. That's causing the issue. This link helped me in figuring out the solution: Oracle JDBC and Oracle CHAR data type

Unknown column 'readingid' in 'where clause'

SELECT
a.objid AS acctid,
a.acctno,
a.name,
a.meterid,
m.serialno,
(
SELECT
objid
FROM
waterworks_meter_reading r
WHERE r.meterid = a.meterid
AND r.month = 6
AND r.year = 2015
LIMIT 1
) AS readingid
FROM waterworks_account a
INNER JOIN waterworks_meter m ON a.meterid = m.objid
INNER JOIN waterworks_account_address ad ON a.objid = ad.parentid
WHERE ad.barangayid LIKE '%'
AND readingid IS NULL
When I tried to execute the query above it throws an error: Unknown column 'readingid' in 'where clause'. Can someone explain to me why?
In SQL, you cannot reference a column alias defined in a select in the where clause at the same level (or elsewhere in the select).
MySQL has a convenient work-around, in some cases. You can reference it in a having clause. So this should do what you want:
WHERE ad.barangayid LIKE '%'
HAVING readingid IS NULL
I think the problem is that the "readingid" isn't really a column name. It exists in the select but that happens after the where clause. I would use a nested query to get the "readingid" so it is available for the where clause.
For example:
SELECT
a.objid AS acctid,
a.acctno,
a.name,
a.meterid,
m.serialno FROM waterworks_account a
INNER JOIN waterworks_meter m ON a.meterid = m.objid
INNER JOIN waterworks_account_address ad ON a.objid = ad.parentid
WHERE ad.barangayid LIKE '%'
AND NOT EXISTS (SELECT
objid
FROM
waterworks_meter_reading r
WHERE r.meterid = a.meterid
AND r.month = 6
AND r.year = 2015)

query inside query to 1 query postgresql

i have a query like this
UPDATE FOLLOWUP F SET CUSTOMER=(SELECT NAME FROM CUSTOMERS C WHERE F.CUST_ID=C.ID), PHONE=(SELECT SEARCHKEY FROM CUSTOMERS C WHERE F.CUST_ID=C.ID);
this is succesfully working in my postgresql, but not running in java
and my java function
for (final TicketLineInfo l : ticket.getLines())
if(l.getConsumption()!= 0.0 && l.getMultiply()!=l.getConsumption()) {
new PreparedSentence(s
, "UPDATE FOLLOWUP F SET CUSTOMER=(SELECT NAME FROM CUSTOMERS C WHERE F.CUST_ID=?), PHONE=(SELECT SEARCHKEY FROM CUSTOMERS C WHERE F.CUST_ID=?);"
, SerializerWriteParams.INSTANCE
).exec(new DataParams() { public void writeValues() throws BasicException {
setString(1, ticket.getCustomerId());
setString(2, ticket.getCustomerId());
}});
}
when i run this
i get error like this:
com.openbravo.basic.BasicException:
org.postgresql.util.PSQLException: ERROR: more than one row returned by a subquery used as an expression
org.postgresql.util.PSQLException:
ERROR: more than one row returned by a subquery used as an expression
my question is how do i convert the above query into one single query without a subquery.. so that i can avoid this exception and proceed with my execution OR is there any other serializer which supports this
Looks like you don't need subqueries in your query:
update FOLLOWUP as F set
Name = c.Name,
Phone = c.SearchKey
from CUSTOMERS as c
where
F.Cust_ID = C.ID and
F.Cust_ID = ?

Categories

Resources