Below is my PrepareStatement code. It does not generate correct SQL-query.
Also it does not come beyond 1st println-statement. Also it says ** NOT SPECIFIED ** in the query (please see below).
How can we fix this, please?
ps1 = con.prepareStatement(
"select stuId, name, relationsName, houseAddress, houseNumber from temp where "
+ " stuId like '?%' and "
+ " sex = '?' and "
+ " name like '?%' and "
+ " age BETWEEN ? and ? and "
+ " relationsName like '?%' "
+ " order by name asc limit 0, 150000 "
);
System.out.println("ps1 Before : " + ps1);
output:
ps1 Before : com.mysql.jdbc.JDBC4PreparedStatement#14d55de: select
stuId, name, relationsName, houseAddress, houseNumber from temp where
stuId like '?%' and sex = '?' and name like '?%' and age BETWEEN **
NOT SPECIFIED ** and ** NOT SPECIFIED ** and relationsName like '?%'
order by name asc limit 0, 150000
It does not come beyond this point. Also it says NOT SPECIFIED in the query (please see to the end).
Any insights please?
ps1.setString(1, stuId);
ps1.setString(2, gender);
ps1.setString(3, name);
ps1.setInt(4, startAge);
ps1.setInt(5, endAge);
ps1.setString(6, relationsName);
System.out.println("ps1 After : " + ps1);
rs = ps1.executeQuery();
because the placeholders where enclosed with single quotes, thus making it a value an not a parameter anymore. you should get rid of it, eg
ps1 = con.prepareStatement(
"select stuId, name, relationsName, houseAddress, houseNumber from temp where "
+ " stuId like ? and "
+ " sex = ? and "
+ " name like ? and "
+ " age BETWEEN ? and ? and "
+ " relationsName like ? "
+ " order by name asc limit 0, 150000 "
);
for LIKE statement, you should concatenate the value in java, not in sql,
ps1.setString(1, stuId + '%');
Related
I'm trying to make a prepared statement and the drivers are working how I assume they are supposed to but the only problem is that my query is no longer valid.
I'm trying to write this query:
SELECT ip_address
FROM log_activity
WHERE created_at
BETWEEN "2017-01-01 00:00:00"
AND DATE_ADD("2017-01-01 00:00:00", INTERVAL 1 HOUR)
GROUP BY ip_address
HAVING COUNT(*) > 200;
But after inserting the parameters for the prepared statement it comes out as:
SELECT ip_address
FROM log_activity
WHERE created_at
BETWEEN '\'2017-01-01 00:00:00\''
AND DATE_ADD('\'2017-01-01 00:00:00\'', INTERVAL 1 'hour')
GROUP BY ip_address
HAVING COUNT(*) > 200;
Which is no longer valid SQL. So how do I remove these quotations from the parameters or what is a good way to work around this?
...
String startDateArg = "'" + args[0].split("=", 2)[1].replace(".", " ") + "'";
String durationArg = args[1].split("=", 2)[1];
int thresholdArg = Integer.parseInt(args[2].split("=", 2)[1]);
String duration = durationArg.equals("hourly") ? "hour" : durationArg.equals("daily") ? "day" : null;
String getUsersOverAPILimitQuery = "" +
"select ip_address " +
"from log_activity " +
"where created_at " +
" between ?" +
" and date_add(?, interval 1 ?) " +
"group by ip_address " +
"having count(*) > ?;";
PreparedStatement preparedStatement = con.prepareStatement(getUsersOverAPILimitQuery);
preparedStatement.setString(1, startDateArg);
preparedStatement.setString(2, startDateArg);
preparedStatement.setString(3, duration);
preparedStatement.setInt(4, thresholdArg);
System.out.println(preparedStatement);
ResultSet getUsersOverAPILimit = preparedStatement.executeQuery();
while (getUsersOverAPILimit.next()) {
String ip_address = getUsersOverAPILimit.getString("ip_address");
System.out.println(ip_address);
}
...
Instead of this:
String startDateArg = "'" + args[0].split("=", 2)[1].replace(".", " ") + "'";
Do this:
String startDateArg = args[0].split("=", 2)[1].replace(".", " ");
no need to add in the single quotes, the preparedstatement does it for you.
Normally we perform the ignore case as follow:
select * from user where UPPER(username) = UPPER('maker1');
Is this any way to do it in where clause condition?
I understand that we can do as follow:
select * from user where UPPER(username) in ( UPPER('maker1'), UPPER(maker2) );
But how about do it in preparedStatement ?
For example:
sb.append( "AND functionType IN (:functionType) " );
map.put( "functionType",
command.getListValues( command.getAllNonTradeFunctionsList( ) ) );
query.setProperties( map );
what is the issue you are facing here is the simple example demonstrating your problem
String query =
"SELECT agent.familyname, agent.givenname"
+ " FROM agent"
+ " WHERE agent.agentid = ?"
+ " AND ("
+ " familyname ilike ? OR givenname ilike ?"
+ ") "
+ " ORDER by familyname";
pst.setInt(1, piececreation.agentid);
pst.setString(2, agent_lastname.toLowerCase());
pst.setString(3, agent_name.toLowerCase());
let't me know if any other help needed
If i insert a quote symbol " in the codContract parameter I receive the following error.
Error querying database. Cause: java.sql.SQLSyntaxErrorException:
ORA-00972: identifier too long
The error may exist in mappers/existence.xml The error may involve
com.iv.queryinterface.AssistenzaMapper.getTitlesFromCodContratct-Inline
The error occurred while setting parameters
SQL:
SELECT t.id_title,
c.des_lastname,
c.des_firstname,
to_char(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW,
DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE
FROM Ivf_Policy p,
Ivf_Title t,
Ivg_Client c,
Ivf_Price pr
WHERE Cod_Contract = TEST
AND p.id_policy = t.id_policy
AND t.cod_type_title IN(2, 3, 13)
AND t.cod_statustitle IN(1, 2)
AND t.cod_client = c.cod_client
AND t.id_price = pr.id_price;
Cause: java.sql.SQLSyntaxErrorException: ORA-00972: identifier too
long
In this example, i set " TEST as value for the codContract parameter. My questions are:
Is this an exploitable SQL injection or a false positive that just prints an sql error into the stack trace?
The code is susceptible to SQL injection, and does no escaping. All that is avoidable by the use of PreparedStatement. Where the query string is not composed dynamically.
Now "TEST is the first part of an SQL identifier till a closing double quote.
I do not want to instruct readers on hacking, but think what something like
"'' OR 1=1 "
+ "UNION SELECT u.login, u.password, '', '', '', '' "
+ "FROM users"
+ "\u0000-- ";
might reveal on data.
Use java.sql.PreparedStatement for avoiding SQL injection.
String query =
"SELECT " +
" t.id_title , " +
" c.des_lastname , " +
" c.des_firstname , " +
" TO_CHAR(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW, " +
" DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE " +
"FROM " +
" Ivf_Policy p, " +
" Ivf_Title t, " +
" Ivg_Client c, " +
" Ivf_Price pr " +
"WHERE " +
"1 = 1 AND " +
" Cod_Contract = ? " +
"AND p.id_policy = t.id_policy " +
"AND t.cod_type_title IN(2, " +
" 3, " +
" 13) " +
"AND t.cod_statustitle IN(1, " +
" 2) " +
"AND t.cod_client = c.cod_client " +
"AND t.id_price = pr.id_price;";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, 'TEST');
ResultSet rs = stmt.executeQuery();
To avoid SQL injection, do not append parameter values directly to SQL queries.
Use bind variables instead.
Thanks.
For an application,I am checking if a table is filled so that I can retrieve that from it; otherwise I will retrive from another table. For that, I use a select and checks if it has null values by wasnull(). If it does, I execute a query; otherwise, I execute a differet query. The problem that I have is when it is null, it does not execute the query but returns null values !
Can you please show me what I am doing wrong or a better solution ?
Here is my code:
String reqEx = "SELECT PYE_DATEDEBUT,PYE_DATEFIN FROM PGEXCEPTPRESENCE WHERE PYE_SALARIE='"+chaine+"' ";
ResultSet rs = stmt.executeQuery(reqEx);
if (rs.wasNull()) {
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from profilpressalarie propressal join profilpresence propres on propressal.ppz_profilpres = propres.ppq_profilpres "
+ "join modelecycle modcyc on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
" on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
" and propressal.PPZ_salarie= '"+chaine+"'";
}
else{
while(rs.next()){
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from PGEXCEPTPRESENCE exc join profilpresence propres on exc.PYE_CYCLEAFFECT = propres.ppq_profilpres join modelecycle modcyc " +
"on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
"on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
"and exc.PYE_SALARIE= '"+chaine+"' ";
}}
rs.wasNull() is meant to be used for verifying the last read column is NULL or not. If your table's first column is a primitive data type like int it will not return NULL. So in this case you need to verify if the query returns any row or not. For this please use the following if condition:
if (!rs.next()) {
req = " select jour.PJO_HORDEBPLAGE1,jour.PJO_HORFINPLAGE1,jour.PJO_HORDEBPLAGE2,jour.PJO_HORFINPLAGE2"
+ " from profilpressalarie propressal join profilpresence propres on propressal.ppz_profilpres = propres.ppq_profilpres "
+ "join modelecycle modcyc on propres.PPQ_CYCLEAFFECT = modcyc.PMO_MODELECYCLE join JOURNEETYPE jour " +
" on modcyc.PMO_JOURNEETYPE= jour.PJO_JOURNEETYPE where modcyc.PMO_ORDREJOUR='"+orderJ+"' " +
" and propressal.PPZ_salarie= '"+chaine+"'";
}
So in my program I have:
private static final String GET_USERS_BY_PARAMS = "select * from user t "
+ "where t.id like %?% "
+ "AND t.name LIKE %?% "
+ "AND t.location LIKE %?% "
+ "AND t.telephone LIKE %?% ";
All of the parameters given above are stored as varchar in the database.
However when I run the following:
statement = connection.prepareStatement(GET_USERS_BY_SEARCH_PARAMS);
statement.setString(1, userID);
statement.setString(2, name);
statement.setString(3, location);
statement.setString(4, telephone());
rs = statement.executeQuery();
I get a SQL exception stating that there was an invalid character. The application throws the error on the executeQuery, so setting the params isn't an issue. I was wondering if this was down to using the % symbols, whihc I included so that you could search without having to input the exact user ID, name, or etc.
Thanks for any help in advance!
The wildcard has to be part of the value passed to the prepared statement. So you need something like this:
private static final String GET_USERS_BY_PARAMS = "select * from user t "
+ "where t.id like ? "
+ "AND t.name LIKE ? "
+ "AND t.location LIKE ? "
+ "AND t.telephone LIKE ? ";
statement = connection.prepareStatement(GET_USERS_BY_SEARCH_PARAMS);
statement.setString(1, "%" + userID + "%");
statement.setString(2, "%" + name + "%");
statement.setString(3, "%" + location + "%");
statement.setString(4, "%" + telephone() + "%");
Btw: what datatype is user.id?
If that is a numeric value, LIKE won't work correctly. You should probably explictely cast the ID to a character value instead: where to_char(t.id) like ?
use CONCAT function,it will works,like this: LIKE CONCAT('%', ?, '%')
or also you can use LIKE ('%' || ? || '%')
You can write with concatenation operator
LIKE ('%' || ? || '%')