How to use SQL Hints on Java query - java

Just heard about 'SQL Hints' to optimize query's result or processing time at typing SQL queries.
I have found plenty of information about how to implement this concept into Hibernate, but nothing about how to use it with plain Java code.
Can anyone help me with this?
We are using the following code:
String value = "someValueToUseAsFilter";
String query = "SELECT /*+ opt_param('_optimizer_cost_model','io') opt_param('optimizer_index_cost_adj',20) opt_param('optimizer_index_caching',65) PARALLEL(4)*/ "+
" T.field AS table_field "+
" FROM table T "+
" WHERE T.field = ? "+
"/";
ResultSet rs = null;
PreparedStatement stmt = null;
try {
stmt = this.connection.prepareStatement(query);
stmt.setQueryTimeout(this.timeout);
stmt.setString(1, value);
rs = stmt.executeQuery();
}
catch (Exception e){
e.printStackTrace();
}
Next, eclipse is throwing the following exception:
java.sql.SQLSyntaxErrorException: ORA-00936: missing expression
The query has been tested and if launched directly against the database it works fine. But keeps returning this error when using it on code.
Can anyone explain me if this is even possible? If so, How can I use it in this context?
Thank you.

As explained in the answer #ahorse_with_no_name linked to, the / is a client directive to end and execute the statement. Your error is nothing to do with the hints or Java, you just need to remove that trailing slash.
You can see the same effect running your statement other ways, e.g. as dynamic SQL in an anonymous block:
set serveroutput on
declare
query varchar2(4000);
begin
query := q'[
SELECT /*+ opt_param('_optimizer_cost_model','io') opt_param('optimizer_index_cost_adj',20) opt_param('optimizer_index_caching',65) PARALLEL(4)*/
T.field AS table_field
FROM your_table T
WHERE T.field = :var
/
]';
dbms_output.put_line(query);
execute immediate query;
end;
/
The generated statement is printed as:
SELECT /*+ opt_param('_optimizer_cost_model','io') opt_param('optimizer_index_cost_adj',20) opt_param('optimizer_index_caching',65) PARALLEL(4)*/
T.field AS table_field
FROM your_table T
WHERE T.field = :var
/
with that trailing slash, and as you say that will run directly in a client/IDE; but the execute immediate gets the same error you do:
ORA-00936: missing expression
ORA-06512: at line 12
The slash is being seen purely as a division symbol, so it's expecting another expression after that - to make the clause WHERE T.field = :var / <something>.
If you remove the slash:
declare
query varchar2(4000);
begin
query := q'[
SELECT /*+ opt_param('_optimizer_cost_model','io') opt_param('optimizer_index_cost_adj',20) opt_param('optimizer_index_caching',65) PARALLEL(4)*/
T.field AS table_field
FROM your_table T
WHERE T.field = :var
]';
dbms_output.put_line(query);
execute immediate query using 42;
end;
/
the generated statement now doesn't have it (obviously), and you don't get the error:
PL/SQL procedure successfully completed.
(I should be selecting into something - the query is only parsed here, not executed, but that doesn't matter for this example).
Note that you also don't need a semicolon on the end of the statement, as that is a statement separator; adding one would cause a different error like ORA-00911 invalid character.

Related

java.sql.SQLException: Before start of result without while loop [duplicate]

ResultSet rs;
rs = this.orderedProduct.select(" sum(unitstoproduce) "," soNo = "+ soNo);
int sum = Integer.parseInt(rs.getString(1));
When i try to execute the above query inside the java class i'm getting an exception as below.
Here the orderedProduct(orderedZnAlProduct) is the table
SELECT sum(unitstoproduce) FROM orderedZnAlProduct WHERE soNo = '15005'
java.sql.SQLException: Before start of result set
I don't see where your query is executed (like statement.executeQuery()) but, this kind of errors generally happens when your cursor is not well positioned. You need to call something likers.next() or rs.first() to move your cursor and then to get the result.
Even I encountered the same problem when I tried to execute
select count(*) TABLE_NAME
But I never encountered the error in any other scenarios when retrieving the values, So I assumed for the queries which have only one row we need to explicitly mention rs.first() and it 'll work like a charm.

ExecuteUpdate with possible single quotes

I have the following code:
sql = update [myTable] set content = '" map.getString() + "' where id = " map.getKey();
stmt.executeUpdate(sql);
This is running in a loop, and map.getString() can return a string with single or double quotes in them. I've tried escaping it with multiple quotes around map.getString() (for example
sql = update [myTable] set content = ''" map.getString() + "'' where id = " map.getKey();
But with no luck.
How can I get it to update the content column with the literal value of map.getString()?
Sample error I receive is: (there are many similar ones)
java.sql.SQLException: Incorrect syntax near 's'.
or
java.sql.SQLException: Invalid SQL statement or JDBC escape, terminating ''' not found.
Avoid using concatenate strings of parameter values for building your request:
it is not safe (possible sql injection)
it is not optimized (as the db engine will have always to parse the request even if always the same string is sent to the db)
it will generated lot of bad conversion error (special character etc)
Prefer using PreparedStatement with bind parameters.
Example:
PreparedStatement stmt = connection.prepareStatement("UPDATE mytable SET content = ? WHERE id = ?");
stmt.setString(1, map.getString());
stmt.setInt(2,map.getKey());
stmt.executeUpdate();
Using bind parameters will avoid conversion mistakes and syntax error you are encountering
Use a PreparedStatement. See http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html . They are precomiled, and thus more amenable for executing in loops as well as handling content containing characters which otherwise require special handling.

How do I call a getter from JDBC?

I am executing an update and I want to insert the value that is returned from my getter into the my table.
statement.executeUpdate("INSERT INTO my_table " +
"VALUES(myClass.getValue(), 'abcd',now())");
I have tried debugging through and I found that the String value and datetime executes correctly. However it gives me an exception when I am calling my getter. The detail message that it shows is FUNCTION myClass.getValue does not exist.
My imports are in order. Any ideas?
statement.executeUpdate("INSERT INTO my_table " + "VALUES("+myClass.getValue() + ", 'abcd',now())");
Your get-call was interpreted as a String because of the missing ' " '.
Take a look at prepared statements, they are easy to read and use and you don't have to struggle with these problems.
Prepared Statement Version (also a lot more secure because they are preventing SQL Injection):
PreparedStatement pst = yourconnection.prepareStatement("INSERT INTO my_table VALUES(?,?,now())";
pst.setString(1,myClass.getValue());
pst.setString(2,"abcd");
pst.executeUpdate();
This is the SQL that you're trying to execute.
INSERT INTO my_table VALUES(myClass.getValue(), 'abcd',now())
You need to pass valid SQL to the executeUpdate method in order for it to run. Java won't interpolate variables and method calls inside strings for you. You have to either concatenate their values into the SQL string that you pass to executeUpdate, or use Prepared Statements instead.
You need to make a method call to your myClass object, not a string. The string will not be executed, its not code, just words.
statement.executeUpdate("INSERT INTO my_table VALUES(" + myClass.getValue() + ", 'abcd',now())");
I'm going to show you how to do it with prepared statements since the other answers did not show you:
PreparedStatement prepStmt = con.prepareStatement("INSERT INTO my_table VALUES( ? , 'abcd',now())"));
prepStmt.setString(1, myClass.getValue());
prepStmt.executeUpdate();
Notice the ?. It will get replaced by your Java call to myClass.getValue().
Please do not concatenate SQL strings.

Issue with exporting portgresql table to CSV in JDBC

I'm using postgresql to host my database. In my database, I have a table say xyz whose structure is as shown below
id content folder
1 hello Inbox
2 hi Sent
I want to export this table to CSV using my java program. The code snippet is below
Connection connection2 = new ServerDBConnect().getConnection();
PreparedStatement statement = connection2.prepareStatement("copy (SELECT * FROM xyz WHERE folder=? ) to 'C:/export.csv' delimiter ','");
statement.setString(1, FOLDER_SELECTED); //Here, FOLDER_SELECTED=Inbox
statement.execute();
When I execute this code, I'm getting SQLException saying
ERROR: there is no parameter $1
If I execute the code without folder specified ("copy (SELECT * FROM xyz) to 'C:/export.csv' delimiter ','")), the code works fine.
What am I doing wrong here? How to go about this problem?
Note: If I execute the query (copy (SELECT * FROM xyz WHERE folder='Inbox' ORDER BY time) to 'G:/export.csv' delimiter ',') directly in the Postgresql SQL console, I'm getting the desired output.
Please help
Ah
I finally found the answer myself.
Small change in the query gave me the desired result
The query is suppose to be like this
Connection connection2 = new ServerDBConnect().getConnection();
PreparedStatement statement = connection2.prepareStatement("copy (SELECT * FROM xyz WHERE folder='" + FOLDER_SELECTED + "' ) to 'C:/export.csv' delimiter ','");
This was driving me crazy, but finally done :-)

statement.execute() returns error with Slash at the end of PL/SQL

When executing pl/sql im obtaining an error :
ORA-06550: line 1, column 316: PLS-00103: Encountered the symbol "/" The symbol "/" was ignored.
PLSQL example:
DECLARE
SQL1 VARCHAR2 (1500);
SQL2 VARCHAR2 (1500);
BEGIN
SQL1 := 'INSERT INTO das_html_caption VALUES (''test_test'')';
SQL2 := 'DELETE FROM das_html_caption where wording = ''test_test''';
EXECUTE IMMEDIATE SQL2;
EXECUTE IMMEDIATE SQL1;
EXECUTE IMMEDIATE SQL2;
COMMIT;
END;
/
Java:
Statement statement = dbConnection.createStatement();
ResultSet rs = null;
boolean ret = statement.execute( sql.getValue() );
is it correct error ? or i'm doing something wrong ?
Thanks
The slash is how you execute the anonymous block through an interactive environment such as SQL*Plus. If you are executing this block by a call from Java you don't need the terminating slash.
Found answer. Had to made more complcated request to google :)
As the message indicates, the compiler
doesn't want to encounter the symbol
"/", so just remove it. That simple.
Let me explain. When using sqlplus or
an SQL worksheet in sqldev, you do
well appending your PL/SQL blocks with
the slash. However, when using the
procedure editor (native to sqldev),
you'll have to remove it. Don't know
why they made this set of rules, but
until they relax them, we'll have to
obey them ;-)
http://forums.oracle.com/forums/thread.jspa?threadID=519670

Categories

Resources