Java + JDBC: Prepared statement failing - java

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.

Related

Check if a table exist in the SQL DB using JdbcTemplate and T-SQL

I am struggling with checking if a table exist in the DB. What I have done so far is as follows:
public boolean isTableExist(String tableName) {
JdbcTemplate jdbc = getJdbcTemplate();
String query =
"IF (OBJECT_ID(?) IS NOT NULL ) "
+ "BEGIN "
+ " PRINT 1 "
+ " RETURN "
+ "END "
+ "ELSE "
+ "BEGIN "
+ " PRINT 0 "
+ " RETURN "
+ "END";
Integer result = jdbc.queryForObject(query, Integer.class, tableName);
return result == 1 ? true : false;
}
Output (Error):
PreparedStatementCallback; uncategorized SQLException for SQL [IF
(OBJECT_ID(?) IS NOT NULL ) BEGIN PRINT 1 RETURN END ELSE BEGIN
PRINT 0 RETURN END]; SQL state [null]; error code [0]; The statement
did not return a result set.; nested exception is
com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not
return a result set.
You can also run a query like so:
select count(*)
from information_schema.tables
where table_name = 'yourtablename'
-- optionally this too
-- and table_schema = 'dbo';
If you get zero, table doesn't exist.
Based on jdbctemplate count queryForInt and pass multiple parameters answer, it seems like you might have to use something like this once you store the query
jdbc.queryForObject(
"select count(*) from information_schema.tables where table_name = ?"
, new Object[] { tableName }
, Integer.class
);
Update:
The problem has been resolved with the help of this post and the final solution based on the above info is:
String query =
"select count(*) "
+ "from information_schema.tables "
+ "where table_name = ? and table_schema = 'dbo'";
Integer result = jdbc.queryForObject(query, Integer.class, tableName);

SQL Statement not working on Oracle JDBC

I have a statement that could retrieve last month's transaction records from Oracle:
select
c.CustomerID as id,
c.Order_ID as txID,
c.Transaction_Date as date1
from
Members a, Verify_Detail b, Verify_Request c
where
a.CustomerID = b.CustomerID AND
b.CustomerID = c.CustomerID AND
b.Order_ID = c.Order_ID AND
c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1))
order by
c.CustomerID, c.Transaction_Date desc
This statement works fine on SQL Developer. But when I use JDBC and Prepared statement to try to fetch my data, it shows me exception 17006: Invalid Column Name, Cause: null all the time.
I'd like to know what is wrong with my statement that made me unable to execute it on JDBC? Isn't it support to be executed if I could use it on Oracle SQL Developer?
Update:
The code that I use is simple:
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/myDBSrc");
Connection con = ds.getConnection();
String sql = "select " +
"c.CustomerID as id, c.Order_ID as txID, c.Transaction_Date as date1 " +
"from Members a, Verify_Detail b, Verify_Request c " +
"where a.CustomerID = b.CustomerID AND b.CustomerID = c.CustomerID AND " +
"b.Order_ID = c.Order_ID AND " +
"c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1)) " +
"order by c.CustomerID, c.Transaction_Date desc";
PreparedStatement pstmt = con.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
out.println("ID: " + rs.getLong("id") + ", txID: " + rs.getString("txID") + ", Date: " + rs.getString("date1"));
}
}
catch(SQLException e){
out.println("SQL state: " + e.getSQLState() + ", Code: " + e.getErrorCode() + ", Msg: " + e.getMessage() + ", Cause: " + e.getCause());
}
This is only a guess, but too large for the comments section...
Maybe you connected the lines in a way that two consecutive lines get merged (in my example, the AND from one line merges with b.CustomerID from the next):
PreparedStatement stmt = conn.prepareStatement("select "+
"c.CustomerID as id, "+
"c.Order_ID as txID, "+
"c.Transaction_Date as date1 "+
"from "+
"Members a, Verify_Detail b, Verify_Request c "+
"where "+
"a.CustomerID = b.CustomerID AND" // <=====
"b.CustomerID = c.CustomerID AND "+
"b.Order_ID = c.Order_ID AND "+
"c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) "+
"and last_day(add_months(trunc(sysdate,'mm'),-1)) "+
"order by "+
"c.CustomerID, c.Transaction_Date desc");
EDIT: I think the reason is much simpler... it's Oracle turning all Identifiers to uppercase, so try this:
String sql = "select " +
"c.CustomerID as \"id\", c.Order_ID as \"txID\", c.Transaction_Date as \"date1\" " +
"from Members a, Verify_Detail b, Verify_Request c " +
"where a.CustomerID = b.CustomerID AND b.CustomerID = c.CustomerID AND " +
"b.Order_ID = c.Order_ID AND " +
"c.Transaction_Date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1)) " +
"order by c.CustomerID, c.Transaction_Date desc";
17006: Invalid Column Name Is raised if you are trying to get not existing column from result set.
1) Option Add external select and try again select * from (your_select)
2) Try to get data with column names.
"ID: " + rs.getLong("CustomerID") + ", txID: " + rs.getString("Order_ID") + ", Date: " + rs.getString("Transaction_Date")
I know there is connection propertie GET_COLUMN_LABEL_FOR_NAME. And if is set to false. ResultSet only knows real column_name. But i'm not sure if ojdbc supports it.

Updating SQL Table with Java

I am developing an application that can update my database... However, I can't get my Java method working correctly. It gives me the following error: Must declare the scalar variable "#P0WHERE". Any suggestions?
The method I am using:
public void updateTable() throws SQLException
{
Scanner input = new Scanner(System.in);
System.out.println("Update the following:\n" + this);
this.getReservationInfo(input);
DataConnection connection = new DataConnection();
String query = "UPDATE " + TableName;
query += "Set Name = ?";
query += "WHERE Person_ID = " + id;
connection.updateData(query, person_name);
connection.closeConnection();
}
Add spaces before 'SET' and 'WHERE', otherwise it will not work.
String query = "UPDATE " + TableName;
query += " SET Name = ?";
query += " , Age = ?";
query += " , Col1 = ?"; //And other cols
query += " WHERE Person_ID = " + id;
EDIT: Changed query to update multiple columns.
I think so. You seem to be missing spaces. After the TableName and after the ?.
String query = "UPDATE " + TableName;
query += " Set Name = ?"; // tableSet not good, and
// ?WHERE is not valid add spaces.
query += " WHERE Person_ID = " + id;

SQL statement works in Workbench but not in Java

The SQL statement below works in mySQL Workbench, but when I execute it in Eclipse, there is an mySQL exeception error. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'by schedule.id' at line 1
String sqlStr = "select movie_db.movie , schedule.date , schedule.timeslot "
+ ", schedule.seats as NoSeats,"
+ " a.bookingsMade, if ( (schedule.seats-a.bookingsMade) is null, schedule.seats,(schedule.seats-a.bookingsMade) ) as availSeats"
+ " ,schedule.movie_id, schedule.id as scID"
+ " from schedule"
+ " left outer join movie_db on ( movie_db.id=schedule.movie_id )"
+ " left outer join ("
+ " select count(*) as bookingsMade, tickets.movie_id as aid from tickets"
+ " group by schedule_id"
+ " ) as a on (schedule.id=a.aid)"
+ " where schedule.movie_id=?"
+ "group by schedule.id";
PreparedStatement pstmt = sqlConnect.getPreparedStatement(sqlStr);
pstmt.setInt(1, Integer.parseInt(movieId));
ResultSet rs = pstmt.executeQuery();
that cannot work:
where schedule.movie_id=?"
+ "group by schedule.id";
change it to
where schedule.movie_id=?"
+ " group by schedule.id";

Why does the PrepareStatement not generate correct SQL query?

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 + '%');

Categories