Sql query with bind variables execution in Jdbc - java

I have a sql query like this.
select "DEPT"."DEPTNO" as "DEPTNO1",
"DEPT"."DNAME" as "DNAME1",
"DEPT"."LOC" as "LOC1",
"EMP"."COMM" as "COMM1",
"EMP"."EMPNO" as "EMPNO1",
"EMP"."ENAME" as "ENAME1",
"EMP"."HIREDATE" as "HIREDATE1",
"EMP"."JOB" as "JOB1",
"EMP"."MGR" as "MGR1",
"EMP"."SAL" as "SAL1"
from "EMP" , "DEPT" where "DEPT"."DEPTNO" in (:DeptNo)
//This is the Jdbc code
Class.forName(DB_DRIVER);
dbConnection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
Statement statment = dbConnection.createStatement();
result = statment.execute(query);//query is above sql query
When i run above query in Oracle sql developer works perfectly.But when i run it with above jdbc code it is throwing Not all variables bound exception.
How to run above query in JDBC

replace :deptno in your query with a ?.
and instead of instantiating statement use the following:
PreparedStatement stmt=con.prepareStatement(query);
stmt.setInt(1,deptno); //1 is for the first question mark
where deptno holds the value for which you want to execute the query.
Through PrepredStatement interface we can use parametrized query which is compiled only once and has performance advantage in comparison to the Statement interface.

You created a Query with bind variable and you never set it.
Use OraclePreparedStatement and its method setStringAtName()
statement.setStringAtName("DeptNo","<<your Value>>");
If not OraclePreparedStatement, you can just put it as ?1 in your Query string
and use,
statement.setString(1,"<<your Value>>");
If in case, you don't know how many bind variables you get, you have capture the bind variables in a map and prepare a list and set it accordingly!
Else your requirement is unachievable!

Get the query dynamically from the report.
From this query we need to split querystring to get number of bind variables and placing those bind variables in a HashMap.HashMap is like
{DeptName =1, Job =1, DeptNo =1}
From this hashmap,need to replace the query bind variable with ?.For this we need to do like
bindkey = entry1.getKey().toString();
String bindkeyreplace =":".concat(bindkey).trim();
String bindkeyreplacestring = "?";
query = query.replace(bindkeyreplace, bindkeyreplacestring);
Then we will get dynamic query coming from the report with ? instead of :bindvariable
PreparedStatement prestmt = dbConnection.prepareStatement(query);
for (int i = 0; i < bindParamMap.size(); i++) {
prestmt.setInt(i + 1, 0);//Setting default value to check the query is running successfully or not
}
result = prestmt.execute();
If in case, we don't know how many bind variables we get then this approach is running successfully for me.

Use this syntax,EMP.DNAME as DNAME1. I mean your dot and as must be inside the double quotes.

The variable DeptNo must be bound to a value before you execute the statement like below.
DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
Statement statment = dbConnection.createStatement();
//Bind deptno to a value
statment.setParameter("DeptNo",5);
result = statment.execute(query);
You must set values for all the variables in your prepared statement othwerise you cannot execute the statement. If you receive the query to execute itself as an input then you should also get the parameters and its values also as input. Something like below
public <returnType> executeQuery(String queryStr, Map<String,Object> params) {
//Code to create connecitno and statment from queryStr.
//Bind deptno to a value
for(int i=0;i<params.size(),i++) {
//Get entry set from map
statment.setParameter(entryset.getKey(),entryset.getValue());
}
result = statment.execute(query);
//return or work on the result
}

Related

Setting the out parameter in callable statement

I'm trying to run a stored procedure that returns a resultSet using oracle jdbc.
The procedure is as follows.
create or replace procedure display_players (rset OUT sys_refcursor)
as
Begin
open rset for select * from player_data;
End;
/
The java code is as follows
try {
sql = "{call display_players()}";
call = conn.prepareCall(sql);
call.execute();
rs = call.getResultSet();
while(rs.next()){
System.out.println(rs.getString("name") + " : " + rs.getString("club"));
}
I tried to register the out parameter as
call = conn.prepareCall("{call display_players(?)}");
call.registerOutParameter(1, OracleTypes.CURSOR);
But that dint work nor is the current code working as i get a null pointer exception which means the result set is not being returned.
how do i achieve this?
I think you haven't quite worked out how to get the result set from an OUT parameter from a stored procedure call.
Firstly, you need to register the OUT parameter, as in your second code sample:
call = conn.prepareCall("{call display_players(?)}");
call.registerOutParameter(1, OracleTypes.CURSOR);
However, once you've executed the statement, it's not correct to call.getResultSet() to get at the result set in the OUT parameter. For example, suppose you were calling a stored procedure that had two OUT parameters returning cursors. Which one should call.getResultSet() return?
The trick is to use call.getObject(...) to get the value of the parameter from call as an Object and then cast this to a ResultSet. In other words, replace the line
rs = call.getResultSet();
with
rs = (ResultSet)call.getObject(1);

How can handle reserved character in SQL query

I want to read data from a table but I got a error because the value I want to compare may contain a word like this: abcd l'jdmd
I try it like this:
String s = "select ref(ad) from adresse_tab ad where ad.ort='"+rs.getString(11)+"' and ad.plz='"+rs.getString(13)+"' and ad.land='"+rs.getString(14)+"'";
PreparedStatement stmt5 = nsdCon.prepareStatement(s);
ResultSet rs5 = stmt5.executeQuery();
The query could look like this:
select ref(ad)
from adresse_tab ad
where ad.ort='Frankfurt am Main'
and ad.plz='65301'
and ad.land='Deutschland'
and ad.strasse='almundo l'tare '
So the problem in this query is this comparison:
ad.strasse='almundo l'tare '
How can I handle reserved character in SQL query?
Please avoid creating a SQL query with supplied parameters using string concatenation. Instead you can continue using PreparedStatement, but use placeholders for the actual param values, and use the statement's set<X>() methods for setting params. Here's official Oracle docs on this.
You must supply values in place of the question mark placeholders (if
there are any) before you can execute a PreparedStatement object. Do
this by calling one of the setter methods defined in the
PreparedStatement class. The following statements supply the two
question mark placeholders in the PreparedStatement named updateSales:
updateSales.setInt(1, e.getValue().intValue());
updateSales.setString(2, e.getKey()); The first argument for each of
these setter methods specifies the question mark placeholder. In this
example, setInt specifies the first placeholder and setString
specifies the second placeholder.
For your case:
String s = "select ref(ad) from adresse_tab ad where ad.ort=? and ad.plz=? and ad.land=?";
PreparedStatement stmt5 = nsdCon.prepareStatement(s);
stmt5.setString(1, rs.getString(11));
... and so on
Use a prepared statement (and for added clarity of named bind variables you can use an OraclePreparedStatement):
String s = "select ref(ad) from adresse_tab ad where ad.ort=:ort and ad.plz=:plz and ad.land=:land";
PreparedStatement st5 = nsdCon.prepareStatement(s);
OraclePreparedStatement ost5 = (OraclePreparedStatement) st5;
ost5.setStringAtName("ort",rs.getString(11))
ost5.setStringAtName("plz",rs.getString(13))
ost5.setStringAtName("land",rs.getString(14))
ResultSet rs5 = st5.executeQuery();
You should not add your query parameters directly to the query string. Use a Prepared Statement instead and pass the query parameters there. See also Does the preparedStatement avoid SQL injection?
The whole point of prepared statements is to use parameters within your query so values can be automatically escaped:
String s = "select ref(ad) from adresse_tab ad where ad.ort=? and ad.plz=? and ad.land=?";
PreparedStatement stmt5 = nsdCon.prepareStatement(s);
stmt5.setString(1, rs.getString(11));
stmt5.setString(2, rs.getString(13));
stmt5.setString(3, rs.getString(14));
ResultSet rs5 = stmt5.executeQuery();
ad.strasse='almundo l'''tare '

why we use setInt with select query instead of using getInt when value is already there in database

why we use setInt with select query instead of using getInt when value is already there in database?
try {
conn = getConnection();
ps = conn.prepareStatement("SELECT * FROM circle where id =?");
ps.setInt(1, circleId);
Circle circle = null;
rs = ps.executeQuery();
if (rs.next()) {
//String s = rs.getString(circleId);
circle = new Circle(circleId, rs.getString("name"));
}
You're setting the value of the parameter to be used in the query. The ? in the SQL represents the parameter, and here you're giving it a value.
When you call getString() later, that's getting a value from the results of the query, which are very different from the parameters sent as part of the query.
Parameterized SQL allows safe inclusion of values into queries, without needing to escape them to prevent SQL injection attacks, or worrying about data type conversions. You should read the JDBC PreparedStatement tutorial for more details.

How to copy table from one database to another?

I need to take a table from one database and upload it to a different database.
So, I create two separate connection . Here is my code
Connection connection1 = // set up connection to dbms1
Statement statement = connection1.createStatement();
ResultSet result = statement.executeQuery("select * from ............. ");
Connection connection2 = // set up connection to dbms2
// Now I want to upload the ResultSet result into the second database
Statement statement2 = connection2.createStatement("insert into table2 " + result);
statement2.executeUpdate();
The above last lines do not work
How can i do this ? The bottomline is how to reuse a ready resultset
ResultSet is a ready java object . I hope there is a way add it to batch or something like this and executeUpdate , but not to write the result set to some temporary space (List, csv etc.) and the insert
The simplest way to do this is with a prepared statement for the insert. It lets you create a single statement object that can be used to run the query multiple times with different parameter values.
try (final Statement statement1 = connection1.createStatement();
final PreparedStatement insertStatement =
connection2.prepareStatement("insert into table2 values(?, ?)"))
{
try (final ResultSet resultSet =
statement1.executeQuery("select foo, bar from table1"))
{
while (resultSet.next())
{
// Get the values from the table1 record
final String foo = resultSet.getString("foo");
final int bar = resultSet.getInt("bar");
// Insert a row with these values into table2
insertStatement.clearParameters();
insertStatement.setString(1, foo);
insertStatement.setInt(2, bar);
insertStatement.executeUpdate();
}
}
}
The rows are inserted into table2 as you iterate through the results from table1, so there's no need to store the whole result set.
You can also use the prepared statement's addBatch() and executeBatch() methods to queue up all the inserts and send them to the database all at once, instead of sending a separate message to the database for each individual inserted row. But that forces JDBC to hold all the pending inserts in memory locally, which it seems you're trying to avoid. So the one-row-at-a-time inserts are your best bet in this case.
If you don't want to manually list out all the field names for every table in the database, you should be able to do this two-step process instead:
Copy the table schema using the answer in this question.
Use resultSet.getMetaData() to get the list of fields, and use that to drive a modified version of the SELECT/INSERT code in #Wyzard's answer.
I will post code here if I get it working.

Java class file from PL/SQL procedure

I have a following PL/SQL procedure:
CREATE OR REPLACE PROCEDURE getDogInfo
(Dog_ID IN NUMBER, Dog_name OUT VARCHAR) AS
BEGIN
SELECT Dog_name INTO Name
FROM Dog_family
WHERE ID = Dog_ID;
END;
I need to make a java class file that does the same. I've been trying like this:
import java.sql.*;
import java.io.*;
public class Procedure {
public static void getDogInfo (int Dog_ID, String Dog_name)
throws SQLException
{ String sql =
"SELECT Dog_name INTO Name FROM Dog_family WHERE ID = Dog_ID";
try { Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement apstmt = conn.prepareStatement(sql);
apstmt.setInt(1, Dog_ID);
apstmt.registerOutParameter(2, java.sql.Types.VARCHAR);
ResultSet rset = apstmt.executeQuery();
rset.close();
apstmt.close(); //Connection close
}
catch (SQLException e) {System.err.println(e.getMessage());
}
}
}
What am I doing wrong? Can someone help me get this working? Thanks
Have alook at this link showing you how to correctly use PreparedStatements.
You will find that the parameter should be ? not Dog_ID
Try
SELECT Name FROM Dog_family WHERE ID = ?
It will also show you how to iterate through your resultSet
Well, you do not tell us what the problem is, but I see several issue right away:
Your select statement should not have an INTO clause. That is a PL/SQL construct. You need to
return the result of the query back as a result set.
Your input parameter, Dog_ID will not be used, because you have not
named the parameter correctly in the SQL statement.
Java string parameters cannot be updated within the method, which I
am assuming that is what you are attempting. You either need to
return a string value from the method, or use a StringBuilder
reference, or some other container to pass in. See this link
There is no "out" parameter to register. Read up on result sets here
So, change your SQL statement to something like this(since you are using a positional parameter as opposed to a named parameter):
"SELECT Dog_name FROM Dog_family WHERE ID = ?"
You should read about JDBC (and Java in general too).
The query should be :
SELECT Name
FROM Dog_family
WHERE ID = ?
(assuming Name is the column name you are selecting from the table - it wasn't clear whether Name or Dog_name was the column name).
Then after you execute the query and get a result set :
String name = null;
if (rset.next()) {
name = rset.getInt (1);
}
...
return name;
Finally, your function should return a String. You can't pass the String as a parameter and update its value. String is immutable in Java.
One more thing - the line apstmt.registerOutParameter(2, java.sql.Types.VARCHAR); is not needed. registerOutParameter is only used with CallableStatement, which is a statement you use to execute a stored procedure.

Categories

Resources