Is it possible to merge these two queries? - java

I'm writing a sql query to count objects. I have about 50 pre-written queries, and each of them is essentially written like so:
"select count(1) from SOME_TABLE where identifier = :ID"
I have it in Java. SOME_TABLE is already written into the query (different for each query). At runtime, a switch/case determines which query to execute and which ID to send it.
Essentially, there are various queries which can be called, but ID is the only thing that changes inside the queries.
So, if I want to count all the pinetrees in a forest, I'd send pineTree as an ID to a query that counts Tree. Simple enough. As I mentioned, there's a giant switch/case which determines TABLE_NAME, ID, and the exact query.
The problem is, I'm trying to count all of the objects of a table, and I'm trying to count them with various IDs. For example:
query1: "select count(1) from LIST_OF_TOYS where animalId = theListOfIDsfromQuery2"
query2: "select allThePetIDs from LIST_OF_PETS where ownerId = :myID
This is essentially what I'm trying to do. I want to count all the toys owned by my pets, but there is no direct link between my ID and the LIST_OF_TOYS table.
I know how to do this with two separate queries, but I would strongly prefer to write one query that just takes ownerId as a parameter, so that I can add it to my giant switch/case (and keep my code neat). I can write the query however I want, but I was wondering if it's possible to do this as a single query and a single argument. Thanks for the help!

select count(1) from LIST_OF_TOYS where animalId in (select allThePetIDs from LIST_OF_PETS where ownerId = :myID)

Related

Use existing JPAQuery as subquery

I have an instance of JPAQuery<?> and need to retrieve the count. However, since the table may contain many items (millions), I want to limit the count to a given maximum, say 50,000.
The current QueryDSL-Code effectively does this:
query.fetchCount();
Now my desired modifications are quite trivial in raw sql:
select count(*) from (<whatever query> limit 50000);
However, I do not know how I would express this in querydsl. The following code is not correct, because .from() takes an entity path, but query is a query:
JPAExpressions.select(Wildcard.all)
.from(query.limit(50000))
.fetchCount();
I am using querydsl 4.
JPAExpressions.select(Wildcard.all) returns a child of SimplyQuery, which you can call limit on.
JPAExpressions.select(Wildcard.all)
.from(entity)
.limit(50000)
.fetchCount();

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.

find column names and metadata from select query without executing the query

I have a scenario, where the user will provide a Select statement. I need to find out the columns (their names, type, and other metadata), but I do not want to execute the query.
I know that I can execute the query and figure it from the ResultSet, but if the query returns many rows, then it may not be a good approach.
For example, consider the query
select name, age from people where people.dob = '1976';
Is there a way of getting the projected column metadata (i.e. metadata of name and age columns) without executing the query?
Solved this by using a PreparedStatement. A PreparedStatement does not execute the statement.

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

Categories