I was writing a prepared statement and for the table name I passed user obtained variable string.
So this works,
String m_table_variable = "blah"; // get from request object
PreparedStatement ps = conn.prepareStatement("select * from "+m_table_variable+"");
While this does not,
PreparedStatement ps = conn.prepareStatement("select * from '+m_table_variable+'")
What triviality am I missing here?
PreparedStatement ps = conn.prepareStatement("select * from " +m_table_variable)
try this
of course if the m_table_variable is a String with name of a table
Your problem is quite straight forward, the first example concatenates three Strings namely "select * from ", "blah" and "" together.
The second example uses one String which literally is "select * from '+m_table_variable+'" and the variable is not concatenated to the final String. Personally I wouldn't dynamically allow the table name to be injected into the SQL statement, read up on SQL injection.
Your first one will not even compile, you need to use \" to insert a quote into a string literal.
You need to escape " from String using \, otherwise it will not compile.
PreparedStatement ps
= conn.prepareStatement("select * from \"m_table_variable\"");
Related
I want to pass a bit as one of the parameters in Prepared Statement. My query should look like this :
query = select * from tbl_security_details('user',O::BIT)
I am framing the query as :
query = select * from tbl_security_details(?,?)
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1,"user")
ps.setString(2,"0::BIT")
However, this throws an error.
Can someone explain how I can pass 0::BIT from the prepare statement without it appending the single quote by itself and getting converted to String ?
Write the prepared statement so that the cast is part of the query:
String query = "select * from tbl_security_details(?, ?::bit)";
java.sql.PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, "user");
ps.setString(2, "0");
That is necessary, because you can only pass a constant value to the prepared statement, not an SQL expression.
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 '
Following is my code line :
ResultSet rs3 = stmt6.executeQuery("SELECT * FROM ShopSystem.Order where s_id="+s_id+" AND status="+Pending);
I am getting the following error :
Unknown column 'Pending' in 'where clause'
What could be the reason... I cant get through it..
No doubt, status is a string, so it needs to be compared to a string. Use delimiters:
SELECT * FROM ShopSystem.Order where s_id="+s_id+" AND status='"+Pending+"'"
Or better yet, learn how to write code that uses parameter substitution for putting parameter values into SQL strings.
Change it to
AND status = '" + Pending + "'"
You need to put the string in quotes. Otherwise the DB thinks you mean a column name.
But actually you should use Prepared Statements. Then you don't need to patch the queries together like this and you don't worry about parameters and escaping them...
Don't make concatenation ! Use prepared statements
PreparedStatement stm = conn.prepareStatement("SELECT * FROM ShopSystem.Order where s_id = ? AND status = ?");
stm.setInt(1, s_id);
stm.setString(2, Pending.name());
ResultSet rs = stm.executeQuery();
you must use the PreparedStatement in this case
// use the ? for the 2 entries values
String selectSQL = new String("SELECT * FROM ShopSystem.Order where s_id=? AND status=?")
preparedStatement = dbConnection.prepareStatement(selectSQL);
// in order you must incialise them here
preparedStatement.setString(1, "s_id");
preparedStatement.setString(2, "Pending");
//execute your resultset `enter code here`
ResultSet rs = preparedStatement.executeQuery();
I'm trying to insert CLOBs into a database (see related question). I can't quite figure out what's wrong. I have a list of about 85 clobs I want to insert into a table. Even when inserting only the first clob I get ORA-00911: invalid character. I can't figure out how to get the statement out of the PreparedStatement before it executes, so I can't be 100% certain that it's right, but if I got it right, then it should look exactly like this:
insert all
into domo_queries values ('select
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = ''CHQ PeopleSoft FS''')
select * from dual;
Ultimately, this insert all statement would have a lot of into's, which is why I just don't do a regular insert statement. I don't see an invalid character in there, do you? (Oh, and that code above runs fine when I run it in my sql developer tool.) And I if I remove the semi-colon in the PreparedStatement, it throws an ORA-00933: SQL command not properly ended error.
In any case, here's my code for executing the query (and the values of the variables for the example above).
public ResultSet executeQuery(String connection, String query, QueryParameter... params) throws DataException, SQLException {
// query at this point = "insert all
//into domo_queries values (?)
//select * from dual;"
Connection conn = ConnectionPool.getInstance().get(connection);
PreparedStatement pstmt = conn.prepareStatement(query);
for (int i = 1; i <= params.length; i++) {
QueryParameter param = params[i - 1];
switch (param.getType()) { //The type in the example is QueryParameter.CLOB
case QueryParameter.CLOB:
Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION);
clob.setString(i, "'" + param.getValue() + "'");
//the value of param.getValue() at this point is:
/*
* select
* substr(to_char(max_data),1,4) as year,
* substr(to_char(max_data),5,6) as month,
* max_data
* from dss_fin_user.acq_dashboard_src_load_success
* where source = ''CHQ PeopleSoft FS''
*/
pstmt.setClob(i, clob);
break;
case QueryParameter.STRING:
pstmt.setString(i, "'" + param.getValue() + "'");
break;
}
}
ResultSet rs = pstmt.executeQuery(); //Obviously, this is where the error is thrown
conn.commit();
ConnectionPool.getInstance().release(conn);
return rs;
}
Is there anything I'm just missing big time?
If you use the string literal exactly as you have shown us, the problem is the ; character at the end. You may not include that in the query string in the JDBC calls.
As you are inserting only a single row, a regular INSERT should be just fine even when inserting multiple rows. Using a batched statement is probable more efficient anywy. No need for INSERT ALL. Additionally you don't need the temporary clob and all that. You can simplify your method to something like this (assuming I got the parameters right):
String query1 = "select substr(to_char(max_data),1,4) as year, " +
"substr(to_char(max_data),5,6) as month, max_data " +
"from dss_fin_user.acq_dashboard_src_load_success " +
"where source = 'CHQ PeopleSoft FS'";
String query2 = ".....";
String sql = "insert into domo_queries (clob_column) values (?)";
PreparedStatement pstmt = con.prepareStatement(sql);
StringReader reader = new StringReader(query1);
pstmt.setCharacterStream(1, reader, query1.length());
pstmt.addBatch();
reader = new StringReader(query2);
pstmt.setCharacterStream(1, reader, query2.length());
pstmt.addBatch();
pstmt.executeBatch();
con.commit();
Of the top of my head, can you try to use the 'q' operator for the string literal
something like
insert all
into domo_queries values (q'[select
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = 'CHQ PeopleSoft FS']')
select * from dual;
Note that the single quotes of your predicate are not escaped, and the string sits between q'[...]'.
One of the reason may be if any one of table column have an underscore(_) in its name . That is considered as invalid characters by the JDBC . Rename the column by a ALTER Command and change in your code SQL , that will fix .
Oracle provide some explanation for ORA-00911. You can got this explanation after executing SQL request in Oracle SQL Developer.
ORA-00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual
But in your case it seems to be double ' character
I am creating a data centric webservice in Java for deployment to Glassfish. All of my methods so far are working correctly except for one.
I am attempting to assign a value from a result set to a variable to use in another SQL statement as per the below code. I am not sure if its possible, or if perhaps my SQL is wrong, but any ideas would be appreciated.
ResultSet rset1 = stmt1.executeQuery("SELECT *
FROM WorkOrder
WHERE WorkOrderID = '"+workOrderID+"'");
Integer custID = rset1.getInt(3);
ResultSet rset2 = stmt2.executeQuery("SELECT *
FROM Customer
WHERE CustID = '"+custID+"'");
Integer quoteID = rset1.getInt(2);
ResultSet rset3 = stmt3.executeQuery("SELECT *
FROM Quote
WHERE QuoteID = '"+quoteID+"'");
What you posted can and should be done in a single query - less complex, and less [unnecessary] traffic back & forth with the database:
SELECT q.*
FROM QUOTE q
WHERE EXISTS (SELECT NULL
FROM CUSTOMER c
JOIN WORKORDER wo ON wo.custid = c.custid
WHERE c.quoteid = q.quoteid
AND wo.workorderid = ?)
The reason this didn't use JOINs is because there'd be a risk of duplicate QUOTE values if there's more than one workorder/customer/etc related.
Additionally:
Numeric data types (quoteid, custid, etc) should not be wrapped in single quotes - there's no need to rely on implicit data type conversion.
You should be using parameterized queries, not dynamic SQL
You foget to invoke ResultSet.next().
if(rset1.next())
{
Integer custID = rset1.getInt(3);
....
}
The note provided by OMG Ponies was really important to take note of, but does not really answer the question. AVD was also correct. I've cleaned it up a bit and included prepared statements. Please use prepared statements. They will help you sleep at night.
PreparedStatement pstmt1 = con.prepareStatement(
"SELECT * FROM WorkOrder WHERE WorkOrderID = ?");
PreparedStatement pstmt2 = con.prepareStatement(
"SELECT * FROM Customer WHERE CustID = ?");
PreparedStatement pstmt3 = con.prepareStatement(
"SELECT * FROM Quote WHERE QuoteID = ?");
pstmt1.setInt(1, workOrderId)
ResultSet rset1 = pstmt1.executeQuery();
// test validity of rset1
if(rset1.next()) {
pstmt2.setInt(1, rset1.getInt(3))
ResultSet rset2 = pstmt2.executeQuery();
// test validity of rset2
if(rset2.next()) {
pstmt3.setInt(1, rset1.getInt(2))
ResultSet rset3 = pstmt3.executeQuery();
}
}