Run multiples queries in single statement under java - java

I would like to select sqlquery from SQLColumn in table1 & then execute the sqlquery in java. However, the query column from table1 contain multiple queries which separated by semicolon.
Table1
Name SQLColumn
------- ------------------------------------
Query1 set nocount on;select * from table2;
Query2 declare item nvarchar(10); select item=data from table2;
Connection conn = ....
PreparedStatement ps = conn.prepareStatement(SQLColumn);
ps.execute();
Any solution on how to run multiple queries in single statement under java other than stored procedure since the normal preparedstatement only support single query per execution?

You could run two separate statements, but inside a single transaction, set to whatever isolation level you want. This would be one way to go here, keeping both statements atomic, meaning that either both complete without error, or else everything would be rolled back.
You commented:
since the normal preparedstatement only support single query per execution?
This may be the case for SQL Server, but some databases actually expose JDBC driver interfaces which do support multiple statements within a single JDBC call. However, this is not considered best practice, as it might expose a security hole of some kind. The transaction suggestion above is a better way to go.

Related

PreparedStatement is faster in Java, How db do it?

I know that PreparedStatement is faster than Statement in Java.
I don't know How oracle db server do it.
PreparedStatement gets pre-compiled In database server -> less work.
It's reduce load on database.
String sql = "SELECT * FROM users u WHERE u.id = ?";
PreparedStatement pstmt = connenction.prepareStatement(sql);
pstmt.setLong(1, userId);
pstmt.executeQuery();
The query is cached in the database server, and compile only once?
If yes, how the database server knows that this query was execute before?
For how long is it cached?
The query is cached in the database server, and compile only once?
More precisely, the query plan is cached on the server. When you run a query, your RDBMS prepares a plan first, then executes it. Preparing a plan requires parsing the query, then analyzing and optimizing it, considering the indexes available and the statistics collected on the participating tables.
If yes, how the database server knows that this query was execute before?
By comparing the string of the query to other queries available in the cache. Since you use parameterized queries, the other query would be textually identical. Caching is the second major reason* to use query parameters: if you were to prepare statements like this
// WRONG! Don't do it like this!
String sql = "SELECT * FROM users u WHERE u.id = "+userId;
PreparedStatement pstmt = connenction.prepareStatement(sql);
all the performance improvements would be gone, because providing a different ID would make it a different query that needs a new plan.
* The top reason for parameterizing queries is, of course, avoiding injection attacks.
You can think of a PreparedStatement as a "cached" statement that will be compiled once on the database server.
When you create the statement, it will be sent to the DB server, which will do the usual syntax checking and determine an efficient execution plan for the query. This way, it can re-use the same execution plan (which is cached as well) for multiple invocations of the same statement.
The key of this cache is the statement itself without its parameter values filled. If the values are explicitly filled in the statement (i.e. you don't fill them using the set* methods), then a new execution plan would be accessed in the cache. That's why prepared statements are best used when executing several statements but with different values.
I use Data Source in my project , where query cache is dependent on connection.
Query cache is maintained per connection (default size is 10).
That means if I have 5 connection , per connection latest 10 prepared statements are cached.

Batch MySQL inserts, one a primary record, one a detail record with foreign key

I have an application that logs a lot of data to a MySQL database. The in-production version already runs insert statements in batches to improve performance. We're changing the db schema a bit so that some of the extraneous data is sent to a different table that we can join on lookup.
However, I'm trying to properly design the queries to work with our batch system. I wanted to use the mysql LAST_QUERY_ID so I wouldn't have to worry about getting the generated keys and matching them up (seems like a very difficult task).
However, I can't seem to find a way to add different insert statements to a batch, so how can resolve this? I assume I need to build a second batch and add all detail queries to that, but that means that the LAST_QUERY_ID loses meaning.
s = conn.prepareStatement("INSERT INTO mytable (stuff) VALUES (?)");
while (!queue.isEmpty()){
s.setLong(1, System.currentTimeMillis() / 1000L);
// ... set other data
s.addBatch();
// Add insert query for extra data if needed
if( a.getData() != null && !a.getData().isEmpty() ){
s = conn.prepareStatement("INSERT INTO mytable_details (stuff_id,morestuff)
VALUES (LAST_INSERT_ID(),?)");
s.setString(1, a.getData());
s.addBatch();
}
}
This is not how batching works. Batching only works within one Statement, and for a PreparedStatement that means that you can only add batches of parameters for one and the same statement. Your code also neglects to execute the statements.
For what you want to do, you should use setAutoCommit(false), execute both statement and then commit() (or rollback if an error occurred).
Also I'd suggest you look into the JDBC standard method of retrieving generated keys, as that will make your code less MySQL specific. See also Retrieving AUTO_INCREMENT Column Values through JDBC.
I've fixed it for now though I wish there was a better way. I built an arraylist of extra data values that I can associates with the generatedKeys returned from the batch inserts. After the first query batch executes, I build a second batch with the right ids/data.

How to update Rows of a JDBC Read Only ResultSet

I'm hitting a problem when trying to update a ResultSet.
I'm querying the database via JDBC, and getting back a resultset which is not CONCUR_UPDATABLE.
I need to replace the '_' into ' ' at the specified columns. How could I do that?
String value = derivedResult.getString(column).replace("_", " ");
derivedResult.updateString(column, value);
derivedResult.updateRow();
This works fine on Updatable, but what if it's ResultSet.CONCUR_READ_ONLY?
EDIT:
This will be a JDBC driver, which calls another JDBC Drivers, my problem is i need to replace the content of the ResultSets, even if it's forward only, or Read only. If I set scroll_insensitive and updatable, there isn't a problem, but there are JDBC drivers that works with forward only resultsets.
Solutions:
Should I try to move the results to an inmemory database and replace the contents there.
Should I implement the resultset which acts like all my other classes: Calls the underlying drivers function with modifications if needed.
I don't want to use the resulst afterward to make updates or inserts. Basically this will be done on select queries.
In my experience updating the result set is only possible for simple queries (select statements on a single table). However, depending on the database, this may change. I would first consult the database documentation.
Even if you create your own resultset which would be updatable, why do you think that the database data would change? It is highly probable (almost certain) that the update mechanism uses code that is not public and only exists in the resultset instance implementation type of the jdbc driver you use.
I hope the above makes sense.

Execute Multiple Select Statement in java

I have to confirm that can we execute multiple select statement in one shot and get multiple resultsets. Please give me some idea for doing this.
I have to execute two select query in one statement:-
String sql="select * form test;
select * from test where empid=1;"
I am expecting to run like this :-
statement.execute(sql);
thanks
I don't believe that standard JDBC supports this. Certainly the ResultSet interface is oriented towards "multiple rows, one row at a time" - but not "multiple sets of results".
That doesn't mean it's not feasible with your specific database, however - it's possible that there's a driver for your database which extends JDBC to allow it. If you specify which database and driver you're using, we could verify that more easily.
In my opinion JDBC does not allow executing multiple statements in one go. The language used in the JDBC specification and API doc indicates that the expectation is that one Statement execution is one statement, not multiple statements (eg it uses 'a SQL statement', which when reading the SQL spec means a single SELECT, INSERT, etc). However it never explicitly states it is not allowed.
Some drivers do support execution of multiple statements in one execution, but this usually has to be explicitly enabled using a connection property. Also some databases support executing a block of stored procedure code without explicitly defining a stored procedure (in that case the block is considered to be the statement).
Create a stored procedure with those set of select statements and use Statement.getMoreResults() to check whether you have more ResultSets and use
Statement.getResultSet() to get the next ResultSet
An example is given Here

JDBC: best way to update a table?

Let's say that I get a ResultSet which was queryed using joins from an sql database.
Is it better to use an sql statement to update the tables or insert new tuples/rows?
Or should i use the resultSet.update() function?
I just want to know the drawbacks associated with each as well as the preferred method of updating tables.
ResultSet will only be updatable if:
You've created your statement with appropriate flag (ResultSet.CONCUR_UPDATABLE)
The underlying database / driver supports updates over join results
If both conditions are true, updates are likely to be more efficient when done this way as you're already holding a cursor to the item. Otherwise you'll need to create a new statement - be sure to use a PreparedStatement for that.

Categories