Determine if JOIN resulted in any columns - java

I have a sql statement with multiple joins; sometimes there are records resulting from the joins and sometimes not. It is not an error when the joins are empty.
Is there a way to test whether a particular join is empty without having to trap the exception occurring when a resulting column is not found in the result set?
In other words, if, using JDBC, I execute the following sql statement:
select * from AA left outer join BB on AA.keyField = BB.keyField
where keyField = "123"
I would like to know whether that join found any fields without having to trap an exception. If I then execute the java statement:
String valueString = rs.getString("BB.keyField");
I get an exception. I cannot compare rs.getString("BB.keyField") to null, because the getString throws an exception if it did not find any values in the join.
I hope this makes the question more clear, and I apologize for not having expanded on it more in the first place.

The query won't return columns with such names. It will just use the simple names of the columns (name, keyField, etc.). Execute the query inside your database query tool, and you'll see which names are assigned to the retrieved columns.
You should never do a select *, and always select specific columns. And you should assign aliases to columns if two columns have the same name:
select AA.id as aId, AA.name as aName, BB.id as bId, BB.name as bName from ...
And, then, you can safely use
rs.getString("aId");
rs.getString("bName");
...
Also, the exception thrown contains a message, which should help you identify the problem. Read it. And if you don't understand it, post it.

Related

Does the JDBC specification define what happens if you call `ResultSet.getObject(String)` for a query which has conflicting column names?

I found a SQL query in some Java code that looks like this:
SELECT * FROM tableA JOIN tableB ON ...
Both tableA and tableB contain the field named id, and the Java code that executes this query does this:
Integer id = (Integer)rs.getObject("id");
Does the JDBC spec have anything to say about which field value will be returned? I haven't been able to find anything that says one way or another. I see that some databases throw an error but MySQL/MariaDB (the database in use, here) do not complain and the value returned seems to be tableA.id, or the "leftmost" field whose name is "id".
I'm asking if there is spec-defined behavior in this case, or if it's up to the database and/or JDBC driver to decide how to behave.
Needless to say, I'll be fixing this to work predictably and unambiguously while I'm looking at the code, but I'm curious as to the answer.
The API documentation of ResultSet answers your question:
Column names used as input to getter methods are case insensitive.
When a getter method is called with a column name and several columns
have the same name, the value of the first matching column will be
returned.
The JDBC 4.3 specification document in section 15.2.3 Retrieving Values also says:
The columns are numbered from left to right, as they appear in the
select list of the query, starting at 1.
Column labels supplied to getter methods are case insensitive. If a
select list contains the same column more than once, the first
instance of the column will be returned.
The index of the first instance of a column label can be retrieved
using the method findColumn. If the specified column is not found,
the method findColumn throws an SQLException.
So, if a result set has multiple columns with the same (case insensitive(!)) name, then the value of the first matching column is returned.

How to determine type of the sql query for jdbcTemplate in JAVA?

My requirement is I want to determine type of sql query so that I can choose jdbcTemplate method accordingly.
Suppose my sql query is of type insert or update then I will choose
String sql ="insert/update sql query";
jdbcTemplate.update(sql);
jdbcTemplate method and if type of my sql query is select then I will choose
String sql ="select sql query";
jdbcTemplate.query(sql);
jdbcTemplate method.
How to determine type of sql query in java effectively?
Which jdbcTemplate method to choose if my query contains both update and select sql statements? e.g.
update table set column_name="abc" where column_name in (select
column_name from table where column_name ="xyz");
Update: In reality I am accepting sql queries from the users of my application from the web form so that is the reason where actual problem arises because user can post any type of sql query through form and I want to choose specific jdbcTemplate method depending upon type of query.
in Oracle you can parse a query before executing it
declare
l_theCursor integer default dbms_sql.open_cursor;
begin
dbms_sql.parse( l_theCursor, 'SELECT 1 FROM DUAL', dbms_sql.native );
end;
which is a good practice anyway since you will be receiving your SQL from user input. if the statement is not valid you will get the appropriate error message. Of course the statement is not executed by the above.
After parsing the statement you can query v$sql to find out the command_type:
select command_type, sql_text
from v$sql t
where sql_text = 'SELECT 1 FROM DUAL';
The various commands_types are like so:
2 -- INSERT
3 -- SELECT
6 -- UPDATE
7 -- DELETE
189 -- MERGE
you can get the full list by select * from audit_actions order by action
Hope that helps :)
SELECT subqueries are irrelevant for the final result. So the command, the first verb is indicative of the result (int updateCount vs. ResultSet).
boolean isSqlSelect = sql.toUpperCase().startsWith("SELECT")
|| sql.toUpperCase().startsWith("WITH");
You can run an SQL UPDATE query via the .select() method, and you can run an SQL SELECT query via the .update() method.
So why are there 2 different methods?
The update method returns a single number; this number represents the amount of changed/created rows.
The select method returns a resultset, which is like a little table: It has a number of (typed and named) columns, and you can walk through the resultset, getting a row's worth of data every time.
In practice, running a SELECT SQL statement via .update() will run the select (and if that select somehow writes to the DB, for example because you run SELECT NEXTVAL('someSequence'), those effects do occur, but you get 0 back because it didn't change/add any rows to any tables. If you run an UPDATE SQL via .select(), the updates go through, and you get an empty resultset back, or possibly a resultset with 1 column of some numberic type, and one row, with the one value that row has being equal to the update count. It depends on the JDBC driver.
There's another method (execute), which returns nothing. The same applies here: If you run an UPDATE via this method, it still works, you just don't get the updatecount back.
My advice: Use .select for all of it, and write a nice renderer that reports the resultset back to the user.
If you'd like to investigate some code that's already done all this, check out the h2 console.

How to execute a SQL statement in Java with many values in a single variable in where in clause

I have to execute below query through JDBC call
select primaryid from data where name in ("abc", adc", "anx");
Issue is inside in clause I have to pass 11000 strings. Can I use prepared statement here? Or any other solution any one can suggest. I dont want to execute the query for each record, as it is consuming time. I need to run this query in very less time.
I am reading the strings from an XML file using DOMParser. and I am using sql server db.
I'm just wondering why you would need to have a manual set of 11,000 items where you need to specify each item. It sounds like you need to bring the data into a staging table
(surely it's not been selected from the UI..?), then join to that to get your desired resultset.
Using an IN clause with 11k literal values is a really bad idea - off the top of my head, I know one major RDBMS (Oracle) that doesn't support more than 1k values in the IN list.
What you can do instead:
create some kind of (temporary) table T_NAMES to hold your names; if your RDBMS doesn't support "real" (session-specific) temporary tables, you'll have to add some kind of session ID
fill this table with the names you're looking for
modify your query to use the temporary table instead of the IN list: select primaryid from data where name in (select name from T_NAMES where session_id = ?session_id) or (probably even better) select primaryid from data join t_names on data.name = t_names.name and t_names.session_id = ?session_id (here, ?session_id denotes the bind variable used to pass your session id)
A prepared statement will need to know the number of arguments in advance - something along the lines of :
PreparedStatement stmt = conn.prepareStatement(
"select id, name from users where id in (?, ?, ?)");
stmt.setInt(1);
stmt.setInt(2);
stmt.setInt(3);
11,000 is a large number of parameters. It may be easiest to use a 'batch' approach as described here (in summary - looping over your parameters, using a prepared statement
each time)
Note - if your 11,000 strings are the result of an earlier database select, then the best approach is to write a stored procedure to do the whole calculation in the database (avoiding passing the 11,000 strings back and forth with your code)
You can merge all your parameter strings into one bitg string separating by ';' char
bigStrParameter=";abc;adc;anx;"
And use LOCATE to find substring.
select primaryid from data where LOCATE(concat(';',name,';'),?)>=0;

How can get the last value of column

How can I retrieve the last entered value of the column in the database (MS ACCESS 2007)
I used the following code
String sql = "SELECT Last(RegNumber) FROM Death ";
but it does not work in MS ACCESS and when I run the program Error generates as
java.sql.SQLException: Column not found
but I have created a column in database as RegNumber
I am using Java for programming in which I used this query
EDIT:
RegNumber is in String form not in integer form so I cant use DESC or ASC
Please help me
Sort your table by whatever criteria you'd like and use SELECT TOP 1 * FROM myTable ORDER BY RegNumber ASC.
Or ORDER BY incrementingId DESC
Basically there must be some logical order to the sorting for what you refer to as the "last entered column" (which I assume means row, not column)
EDIT: Your function is correct in Access, and should return the correct value. However Java may not interpret it correctly. Try your query in an Access native query, then try debugging your Java. If it's simply that Java does not support this function, consider using the built in ResultSet() functions in Java.sql
ResultSet rs = ....;
rs.last();
int RegNumber = rs.getRow();
I do not know about the last() function in MS ACCESS, but I have another idea:
Usually there is an automatically generated id for each table, so you can sort on it and get the first record from the result set like this:
SELECT RegNumber
FROM Death
ORDER BY id DESC
That depend of your database structure.
Typically with table come some unique identifier, if you are sure that it comes always in order to database you could use function MAX to retrieve the identifier and then whole row.
Another scenario is just to a timestamp columns that describe the time when column was created , this approach satisfying if the sequence is really crucial if not the id should be enough.
Following will return the last and lastest RegNumber :
SELECT RegNumber FROM Death ORDER BY RegNumber DESC

Query problems with Hibernate (JPA) and PostgreSQL

I'm trying to use PostgreSQL as the database for Hibernate/JPA. However, I get an error when executing a simple query. My query is as follows:
SELECT DISTINCT p FROM UserProfile p ORDER BY :order
When I execute the query, I'll pass in a value like "lastLoginDate" for :order. However, I get the following exception when trying to execute the query:
ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
Position: 781
This query works just fine using MySQL as the database, but we'd like to move towards PostgreSQL. My overall configuration and database connection is correct, as I see the tables being created properly. Is there something I'm missing? Is there a configuration property I need to set? Any help you can give would be MUCH appreciated. Thanks!
Postgresql prohibits that query because it is ambiguous:
there's actually a definitional reason for it. Consider
SELECT DISTINCT x FROM tab ORDER BY y;
For any particular x-value in the table there might be many different y
values. Which one will you use to sort that x-value in the output?
It's not very clear what you want (an example?), but if you intend to sort all records by ':order' column, and then remove duplicated values, you can do that first with DISTINCT ON: , and then reorder:
SELECT p FROM
( SELECT DISTINCT ON (p) * from UserProfile ORDER BY p , :order)
AS UserProfileUniq
ORDER BY :order ;

Categories