I execute the following queries:
SELECT 1; CREATE TABLE ....; SELECT 2;
after that I try to get all resultSets. I use the following code for this:
while(!stmt.getMoreResults()) {
stmt.getResultSet();
}
Unfortunately I get jus first result set. Please tell me what I'm doing wrong?
Your second CREATE TABLE statement technically does not even return a result set (though JDBC might return a count of the records affected by DML). So, if you want to capture the conceptual return value of each statement, then you should just run them separately.
If your second statement were actually a SELECT, then perhaps we could find some way to combine the queries together.
Read this canonical answer to see how to handle the case where you really do have mulitple selects. But, note that not all databases support this (e.g. Oracle does not support it). And read here to see why multiple queries in a single JDBC call might even be a bad thing.
Are you trying to say that Java is just not capable of doing the thing .Net does without a hitch? Is it as simple as that?
No matter what kind of dummy statements are between selects in the script that is run as batch the bool IDataReader.NextResult() in the C# code reliably returns next result jumping over the next dummy statements for Netezza we are trying to debug for now. It did the same thing for many years for all the platforms that support batch calls in case we had to deal with them.
Related
My Scenario is i have big query with lot of joins and lot of decode/case calls in select and i am passing one param to where condition from java and i see for 150000 rows java fetch is very slow but query is running faster in SQL developer client interface.
i thought of creating or replacing a view which takes one parameter and call that view from java.
Did not find resource to know how to pass prams to create or replace view statement from java ?
Any one suggest other approach that fetches rows quickly ?
Using oracle 12c and driver is jdbc7 and jdk8
First (and easiest):
Set the JDBC fetch size to a high number in your statement. There is a setFetchSize(int) method on Statement, PreparedStatement, CallableStatement, and ResultSet objects.
This defaults to something small like 10 rows. Set that to a reasonably high number, such as 500 or more.
This is a setting that will definitely slow down a query that pulls back hundreds of thousands of records.
Second:
Verify that the query is indeed running fast in SQL Developer, to the last row.
You can export to a file or try wrapping the query in a PL/SQL statement that will loop through all records.
If you wish, you can use AUTOTRACE in SQL*Plus to your advantage:
SET TIMING ON
SET AUTOTRACE TRACEONLY
<your query>
This will run the query to the end, pulling all records over the network but not displaying them.
The goal here is to prove that your SQL statement is indeed returning all records as quickly as needed.
If not, then you have a standard tuning exercise. Get it running to completion quickly in SQL Developer first.
The functionality that discussed within this question is to execute the given SQL script. The content of the script is intended to be defined by the user during application runtime. The script can be whether one INSERT statement or a sequence of complex PL/SQL statements. Since the input available during runtime (eventually as String instance) it should be executed through Java.
Current approach is wrapping user input with a PreparedStatement and to execute it. This solution works for the existing test cases. The main concern is to provide the full functionality of the used database that might be not covered by tests, i.e. solution that is closest to passing the same user SQL script into database vendor's provided console.
I'm wondering are there any not envisaged limitations in current approach with PreparedStatement? Is there any better general approach for SQL script execution via Java?
Well, this is a broad design question but I think that there are several steps that could be done:
SQL script parsing and recognition: You need to be able to detect which type of SQL script you have: PL/SQL, DML, DDL, CDL, TCL, multipart separated by ";" etc.
Statement building: for each type of sql script you need to be able to execute the statement with java.
Parsing the result. You need to be able to collect the returned in SELECTs and optionally parameters returned by functions or number of affected/inserted rows.
Error handling: you need to be able to report what happened to the SQL Script when things didn't worked as expected.
Please consider:
This seems like the programming of a SQL Client. If not please explain what do you want to do. Do not use this as the connection layer in a normal application. It will be extremely inefficient and vulnerable to SQL injections (It is much more complicated than just scaping commas)
You may want to call functions o execute queries with external parameters.
This does not includes the user interfaces features like Syntax highlighting. Parameters interfaces, etc...
The first limitation of PreparedStatement that comes to mind - you won't be able to register an OUT parameter(s) of a stored procedure, you may wish to look into CallableStatement interface.
I am writing a DAO layer IN Java for my Tomcat server application,
I wish to use Prepared Statement wrapping my queries (1. parsing queries once, 2. defend against SQL injections),
My db design contains a MyISAM table per data source system. And most of the queries through DBO are selects using different table names as arguments.
Some of this tables may be created on the fly.
I already went though many posts that explain that i may not use table name as an argument for Prepared statement.
I have found solutions that suggest to use some type of function (e.g. mysql_real_escape_string) that may process this argument and append the result as a string to the query,
Is there any built in Jave library function that may do it in the best optimized way, or may be you may suggest to do something else in the DAO layer (i do not prefer to add any routines to the DB it self)?
Are you able to apply restrictions to the table names? That may well be easier than quoting. For example, if you could say that all table names had to match a regex of [0-9A-Za-z_]+ then I don't think you'd need any quoting. If you need spaces, you could probably get away with always using `table name` - but again, without worrying about "full" quoting.
Restricting what's available is often a lot simpler than handling all the possibilities :)
If you want to be extra safe than you can prepare a query and call it with supplied table name to check if it really exists:
PreparedStatement ps = conn.prepareStatement("SHOW TABLES WHERE tables = ?");
ps.setString(1, nameToCheck);
if(!ps.executeQuery().next())
throw new RuntimeException("Illegal table name: " + nameToCheck);
(The WHERE condition might need some correction because I don't have mysql under my fingers at the moment).
first of all, a preface: I'm writing a java class that creates temporary tables on a database using jdbc. I'm using JSE6 and Oracle 11XE as a test DB, but the class needs to be also DB2 compliant.
The temporary tables I'm trying to create come from a bigger one, and I do some filtering and aggregations on the data. The parameters I base my filtering on are decided by the user at runtime. One simplified example of what I'm trying to do is this:
CREATE TABLE temp_table AS (
SELECT
table1.department_id,
SUM(CASE WHEN table1.number_1 < &1 THEN table1.number_1 ELSE 0 END)) AS column1
FROM
table1
GROUP BY table1.department_id
)
My problem is that I need to specify parameters to filter the data, and I need to be sure they're properly escaped/localized/typed. This would be easy using a prepared statement, but I cannot use bind variables with DDL.
The temporary solution I resorted to is to alter the query String myself, writing the parameters in the correct place, but this means I now have to implement all the checks instead of relying on a PreparedStatement object to do it for me, on top of losing all the other benefits.
I investigated other solutions, but none of them convinced me so far:
I could first create an empty temp_table and then fill it with INSERT INTO temp_table(id, column1) (SELECT ...) but it seems I might incur in performance loss, so I'd like to stick to the CREATE temp_table AS
I thought about creating a temporary statement to hold the inner SELECT query, and have it generate a properly formatted/localized/etc. query string, but I haven't found any way to obtain the final query from it (and I read it's definitely not possible here). The only option I found for this case is to use DebuggableStatement, but I'm not sure I can include it in the project (also, it seems a quite inelegant way of solving my problem)
Another solution I'm thinking of, is to simply put the queries that create the temporary tables (for each of them I'd put the whole CREATE AS (SELECT...) on the database, inside a procedure, which I'll then be able to call using CallableStatement. this way I could avoid handling typization and still have good performances, at the price of a tighter coupling with the db (I'd have to be sure the procedures are there, or manage in java their addition/removal from the db)
So, my question is: are there better alternatives than the ones I could think of?
Is this supposed to be database agnostic, or are you targeting for only Oracle? You don't have to store PL/SQL in a stored procedure to use it; just build an anonymous PL/SQL block that does what you need, and execute it. The anonymous PL/SQL block can be built dynamically so that strongly typed variables are declared in the PL/SQL to hold your parameters, and then your java code sticks the values in. The type safety wouldn't be handled by Java since you're just building a string; it would be handled by Oracle when you execute the anonymous PL/SQL block.
I'm trying to do pagination from the db and so far I have found that if you want to use limit you should use SQL_CALC_FOUND_ROWS.
However, in Java I'm having some issues understanding how to call this.
Can I do it in one prepareStatement or will I need to make multiple calls? If im making multiple calls, how does MySQL know I'm referring to the last call for the count?
Thanks.
You'll have to make two calls (unless you implement a some stored function in the db which returns both the limited resultset and the count, which I assume is possible in mysql but never tried that).
MySQL will know what query counts to return because both the query with the limit and the SELECT FOUND_ROWS(); will be in the same session.