JDBC - Multiple queries in NamedParameterJdbcTemplate - spring

Is there any way I can execute more than 1 query using a NamedParameterJdbcTemplate in one single call?

The simple answer: You can't. JDBC statements should execute only one query / statement at a time.
The longer answer: You usually can't, because either the driver or the database server doesn't support it, and formally the JDBC specification doesn't allow for it (if you read a bit between the lines in both the specification and the Javadoc). However, some driver (ie MySQL Connector/J) do allow you to execute multiple queries in one go (though you might need to specify a connection property to enable it, not sure).

Related

Details of JDBC PreparedStatement.executeQuery()

When we execute SQL queries using PreparedStatement (as described here http://tutorials.jenkov.com/jdbc/preparedstatement.html), what exactly does the executeQuery() method do, if we use for example a database like SQL Server or Postgres? Does it convert the SQL query directly into a set of database operations, or does it make a network call to a database server that translates the SQL query to the database operations?
This is more generally a question about how databases like SQL Server work. I'm just wondering if they're running on separate servers than the ones calling executeQuery().
The implementations details vary per database system, but in general JDBC drivers for RDBMSes that uses SQL as their native query language will work as follows:
When Connection.prepareStatement(...) is executed, the query is sent to the database server for compilation
On PreparedStatement.executeQuery(), the driver sends an execute command together with the collected parameter values, and the database server executes the statement compiled earlier using those parameter values.
In other words, the driver is not concerned with low-level operations on the database server, but will just send a 'compile' and 'execute-with-parameters' command to the database server, and the database server takes care of the low-level operations.
And to be clear, not all drivers work this way. For example, the MySQL Connector/J by default 'compiles' the statement locally (determines the number of parameters), and on execute it will inline the parameter values (with proper escaping) into the statement, and then send a SQL string with literal values instead of parameters for execution on the database server. However, in that case, the database server is still responsible for determining and performing the necessary low-level operations.
On the other hand, it is entirely possible that a driver for some NoSQL database (or other type of datastore) will translate a SQL query into low-level operations on that datastore.

Can JMeter JDBC pre-processor accept multiple Insert/delete/update queries?

Can JMeter JDBC pre-processor accept multiple Insert/delete/update queries?
I have added two queries:
JMeter can do whatever underlying JDBC driver can do, for example for MySQL you can specify allowMultiQueries JDBC URL parameter and you will be able to separate statements by semicolon.
Looking into oracle pool variable name my expectation is that you're trying to test an Oracle database and its JDBC driver doesn't support this feature.
The options are in:
Create a stored procedure which will delete multiple records
Parameterize existing JDBC PreProcessor using i.e. __StringFromFile() function, in this case you will not have to copy and paste the preprocessors
Use JSR223 PreProcessor instead of the JDBC PreProcessor and implement your records deletion logic there, take a look at Statement.addBatch() function, you can combine multiple queries into one statement with it. Check out Using Statement Objects for Batch Updates chapter of the Retrieving and Modifying Values from Result Sets article for more details.
You can submit multiple queries as is, because you can't use ; in JDBC request
But you can use other techniques to insert/delete multiple records, for example using IN
delete from CPAY where bnf_nic_name in ('BillerBBJ929' ,'BillerOFV864')

Batch updates with Sequel gem

I need to do multiple updates on a PostgreSQL database at once. To make it faster, I would like to avoid continually changing context between my ruby application and the database.
I've learned about the #update_sql method, however my strategy to queue those queries is not working. I'm making a list sqls which holds many update strings, and then db[sqls.join(';') + ';']. If instead of executing this line I decide to print the resulting sql and copy/paste to the database it works.
Why doesn't this work? How can I send multiple updates in a single sql?
Sequel doesn't offer an API that supports multiple queries in a single statement. If the driver you are using supports, it, you can use Sequel::Database#synchronize to get access to the driver connection object, and call methods directly on that.

PreparedStatement and ORA-01652( unable to extend temp segment)

I have a vey huge query. It is rather large, so i will not post it here(it has 6 levels of nested queries with ordering and grouping). Query has 2 parameters that are passed to it via PreparedStatement.setString(index, value). When I execute my query through SQL Developer(replacing query parameters to actual values before it by hand) the query runs about 10 seconds and return approximately 15000 rows. But when I try to run it through java program using PreparedStament with varibales it fails with ORA-01652(unable to extend temp segment). I have tried to use simple Statement from java program - it works fine. Also when I use preparedStatement without variables(don't use setString(), but specify parameters by hand) it works fine too.
So, I suspect that problem is in PreparedStatemnt parameters.
How does the mechanism of that parameters work? Why simple statement works fine but prepared one fails?
You're probably running into issues with bind variable peeking.
For the same query, the best plan can be significantly different depending on the actual bind variables. In 10g, Oracle builds the execution plan based on the first set of bind variables used. 11g mostly fixed this problem with adaptive cursor sharing, a feature that creates multiple plans for different bind variables.
Here are some ideas for solving this problem:
Use literals This isn't always as bad as people assume. If the good version of your query runs in 10 seconds, the overhead of hard-parsing the query will be negligible. But you may need to be careful to avoid SQL injection.
Force a hard-parse There are a few ways to force Oracle to hard-parse every query. One method is to call DBMS_STATS with NO_INVALIDATE=>FALSE on one of the tables in the query.
Disable bind-variable peeking / hints You can do this by removing the relevant histograms, or using one of the parameters in the link provided by OldProgrammer. This will stabilize your plan, but will not necessarily pick the correct plan. You may also need to use hints to pick the right plan. But then you may not have the right plan for every combination of inputs.
Upgrade to 11g This may not be an option, but this issue is another good reason to start planning an upgrade.

Does the compiled prepared statement in the database driver still require compilation in the database?

In the Oracle JDBC driver, there is an option to cache prepared statements. My understanding of this is that the prepared statements are precompiled by the driver, then cached, which improves performance for cached prepared statements.
My question is, does this mean that the database never has to compile those prepared statements? Does the JDBC driver send some precompiled representation, or is there still some kind of parsing/compilation that happens in the database itself?
When you use the implicit statement cache (or the Oracle Extension for the explicit Statement Cache) the Oracle Driver will cache a prepared- or callable statement after(!) the close() for re-use with the physical connection.
So what happens is: if a prepared Statement is used, and the physical connection has never seen it, it sends the SQL to the DB. Depending if the DB has seen the statement before or not, it will do a hard parse or a soft parse. So typically if you have a 10 connection pool, you will see 10 parses, one of it beein a hard parse.
After the statement is closed on a connection the Oracle driver will put the handle to the parsed statement (shared cursor) into a LRU cache. The next time you use prepareStatement on that connection it finds this cached handle to use and does not need to send the SQL at all. This results in a execution with NO PARSE.
If you have more (different) prepared statements used on a physical connection than the cache is in size the longest unused open shared cursor is closed. Which results in another soft parse the next time the statement is used again - because SQL needs to be sent to the server again.
This is basically the same function as some data sources for middleware have implemented more generically (for example prepared-statement-cache in JBoss). Use only one of both to avoid double caching.
You can find the details here:
http://docs.oracle.com/cd/E11882_01/java.112/e16548/stmtcach.htm#g1079466
Also check out the Oracle Unified Connection Pool (UCP) which supports this and interacts with FAN.
I think that this answers your question: (sorry it is powerpoint but it defines how the prepared statement is sent to Oracle, how Oracle stores it in the Shared SQL pool, processes it, etc). The main performance gain you are getting from Prepared statements is that on the 1+nth run you are avoiding hard parses of the sql statement.
http://www.google.com/url?sa=t&source=web&cd=2&ved=0CBoQFjAB&url=http%3A%2F%2Fchrisgatesconsulting.com%2FpreparedStatements.ppt&rct=j&q=java%20oracle%20sql%20prepared%20statements&ei=z0iaTJ3tJs2InQeClPwf&usg=AFQjCNG9Icy6hmlFUWHj2ruUsux7mM4Nag&cad=rja
Oracle (or db of choice) will store the prepared statement, java just send's it the same statement that the db will choose from (this is limited resources however, after x time of no query the shared sql will be purged esp. of non-common queries) and then a re-parse will be required -- whether or not it is cached in your java application.

Resources