Java JDBC Postgres: Select with single quote - java

I've been testing the code over and over found that the issue is the single quote. As you can see in the query below, I used the single quote in the where clause. If I remove that I get a result but if I put it back even though the are rows that satisfies the filter it does not return anything. I also tried to use a view on this. Putting the where clause in the view and selecting the view directly and not using any filter. Still it does not return anything.
try {
Class.forName("org.postgresql.Driver").newInstance();
Connection Conn = DriverManager.getConnection("jdbc:postgresql://{ipaddress}/database?user=postgres&password=password");
Statement Stmt = Conn.createStatement();
String sqlCommand = "SELECT col1_timestamp , col2 FROM table WHERE col1_timestamp > '00:01:00' ";
ResultSet RS = Stmt.executeQuery(sqlCommand);
while (RS.next()) {
data.add(RS.getInt("col1_timestamp ")
+ "=>" + RS.getString("col2"));
}
// Clean up after ourselves
RS.close();
Stmt.close();
Conn.close();
}
catch (SQLException E) {
System.out.println("SQLException: " + E.getMessage());
System.out.println("SQLState: " + E.getSQLState());
System.out.println("VendorError: " + E.getErrorCode());
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
I also already tried:
String sqlCommand = "SELECT col1_timestamp, col2 FROM table "
+ " WHERE col2= ? AND (now() - col1_timestamp::timestamp with time zone) < interval ? ";
PreparedStatement preparedStatement = Conn.prepareStatement(sqlCommand);
preparedStatement.setString(1, "test");
preparedStatement.setTime(2, new Time(new Long(-28680000))); //String(2, "00:02:00");
Still does not work, instead it throws an error on the second parameter.
It's pretty simple task really but it always returns a blank value.
Any idea?

The interval literals are quite limited (in SQL in general and in Postgres) and you can't use a parameter for the unit of the interval literal
If you always have the same unit (e.g. minutes) you can do something like this:
String sqlCommand =
"SELECT col1_timestamp, col2 FROM table " +
" WHERE col2= ? " +
" AND (now() - col1_timestamp::timestamp with time zone) < interval '1' minute * ?";
PreparedStatement preparedStatement = Conn.prepareStatement(sqlCommand);
preparedStatement.setString(1, "test");
preparedStatement.setInt(2, 5); // five minutes
If you need to query for different units (hours, minutes, days) then you either need to use the approriate number of minutes for each of them or change the SQL each time: interval '1' day * ? or interval '1' hour * ?

Related

ORA-00923: FROM keyword not found where expected in SeleniumWebDriver

I created a class (ValidarStatusOsPage) in java that makes a connection to the DB and returns to a test class (ValidateStatusOsTest) the result of the query and prints to the screen.
When I run the test class, the Eclipse console displays the message:
ORA-00923: FROM keyword not found where expecte
I have reviewed the code several times but I can not verify where the error is.
Below is the Java class for connecting to the DB and the test class.
public class ValidarStatusOsTest {
static String query;
#Test
public void validarOs() {
ValidarStatusOsPage os = new ValidarStatusOsPage();
query = os.returnDb("179195454");
}}
public class ValidarStatusOsPage {
String resultado;
public String returnDb(String NuOs) {
// Connection URL Syntax: "jdbc:mysql://ipaddress:portnumber/db_name"
String dbUrl = "jdbc:oracle:thin:#10.5.12.116:1521:desenv01";
// Database Username
String username = "bkofficeadm";
// Database Password
String password = "bkofficeadmdesenv01";
// Query to Execute
String query = "SELECT NU_OS, CD_ESTRATEGIA, CD_STATUS, NU_MATR, DT_ABERTURA" +
"FROM tb_bkoffice_os"+
"WHERE NU_OS ="+ NuOs +"";
try {
// Load mysql jdbc driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// Create Connection to DB
Connection con = DriverManager.getConnection(dbUrl, username, password);
// Create Statement Object
Statement stmt = con.createStatement();
// Execute the SQL Query. Store results in ResultSet
ResultSet rs = stmt.executeQuery(query);
// While Loop to iterate through all data and print results
while (rs.next()) {
String NU_OS = rs.getString(1);
String CD_ESTRATEGIA = rs.getString(2);
String CD_STATUS = rs.getString(3);
String NU_MATR = rs.getString(4);
String DT_ABERTURA = rs.getString(5);
resultado = NU_OS + " " + CD_ESTRATEGIA + " " + CD_STATUS + " " + NU_MATR + " " + DT_ABERTURA + "\n";
System.out.println(NU_OS + " - " + CD_ESTRATEGIA + " - " + CD_STATUS + " - " + NU_MATR + " - "+ DT_ABERTURA);
}
// closing DB Connection
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return resultado;
}}
3 points are there in your query:
SELECT NU_OS, CD_ESTRATEGIA, CD_STATUS, NU_MATR, DT_ABERTURA" +
"FROM tb_bkoffice_os"+
"WHERE NU_OS ="+ NuOs +""
space before FROM missed first part of query is: SELECT NU_OS, CD_ESTRATEGIA, CD_STATUS, NU_MATR, DT_ABERTURAFROM
space missed before WHERE: SELECT NU_OS, CD_ESTRATEGIA, CD_STATUS, NU_MATR, DT_ABERTURAFROM tb_bkoffice_osWHERE NU_OS =
concatenate parameter into SQL string is exact hack point for SQL Injection attack. Never do it in real program even if it is pure standalone. Always use parameters for queries.
and a little last one: + NuOs +"" - last "" has no sense at all...
good luck.
UPD: #YCF_L absolutely right use Prepared statement.
you need to do this:
in Sql String: WHERE NU_OS = ?
in code:
PreparedStatement stmt = con.prepareStatement(query);
stmt.setString(1, NuOs);
//also works: stmt.setObject(1,NuOs);
things to remember with JDBC:
all parameters in SQL are just ? marks
parameter indexes start with 1 (not 0)
and in order they appear in SQL from strat to end
(e.g. Select * FROM tbl WHERE col1=? and col2=?
has parameter 1 for col1 and parameter 2 for col2
PS. your initial SQL has one more error but I'm not going to tell you what is it :-) use parameter and all be fine.

java.sql.SQLException: no such column and false Period getDays result

I'm a java beginner and struggle with two problems.
1) The SQL Exception: no such column 'Ofen'
This is my Code and I want to get specific data from a SQLite Database called "kleintest.db" with 2 tables "maindata" and "Zahlwertuntertable". maindata contains the 'Ofen' entry as TEXT. The ResultSet rs should generally take all Data from maindata and the ResultSet rs2 should take the weight from Zahlwertuntertable. But running the programm now shows the mentioned error.
public static void readDB() {
try {
Statement stmt = connection.createStatement();
//ResultSet rs = stmt.executeQuery("SELECT * FROM Gewichtsabnahme;");
ResultSet rs = stmt.executeQuery("SELECT * FROM maindata;");
ResultSet rs2 = stmt.executeQuery("SELECT * FROM Zahlwertuntertable;");
while (rs.next()) {
System.out.println("Ofen = " + rs.getString("Ofen"));
System.out.println("Platznummer = " + rs.getInt("Zahlwert"));
System.out.println("Startdatum = " + rs.getString("Startdatum"));
LocalDate heute = LocalDate.now();
String Datum = rs.getString("Startdatum");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
LocalDate Wägetag = LocalDate.parse(Datum, formatter);
Period DiffTag = Period.between(heute, Wägetag);
System.out.format("Tage = " + DiffTag.getDays() + "\n"); //
System.out.println("Gewicht = " + rs2.getInt("Startgewicht"));
}
rs.close();
rs2.close();
connection.close();
} catch (SQLException e) {
System.err.println("Zugriff auf DB nicht möglich.");
e.printStackTrace();
}
}
The table maindata contains the following items:
Laufnummer Ofen Zahlwert Startdatum
But Laufnummer is just a primary key and should not be retrieved.
2) Next Question is the thing with the Period function. This worked well but as a printed result I'll get P 1D or P 1M 2D what looks slightly confusing. I like to print just the simple amount of days like 45 or 45D and added the getDays() to my DiffTag. Now my result is -1 what makes no sense at all. What's wrong here?
Period DiffTag = Period.between(heute, Wägetag);
System.out.format("Tage = " + DiffTag.getDays() + "\n");
Thanks for suggestions and links I may have missed. But everything I looked so far didn't point out my specific questions.
You can only have one result set open at a time for a Statement object so when you execute the second query agains "Zahlwertuntertable" the first one gets closed.
So either add another statement or handle one query at a time.
Also, right now it looks strange that you call rs.next() but never rs2.next()

JDBC timeout with ResultSet am I doing it right?

I have a JDBC ResultSet that gives me a TimeOut after only a few thousand rows are processed. I have a few million rows to process, so I'd like to tweak my program to avoid this, just not sure what needs to be tweaked.
Database table is indexed and returns data quickly using selection criteria, so I don't believe it is on the database side. I'm returned 14 columns mixed between address columns and ints. Not a lot of data.
I'm doing a connection.createStatement() and then building the SQL from there. The answer might be I should use a prepared statement.
Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
String jobNameFilter = (Cli.getJobName() != null) ? " AND [JobName] = '" + Cli.getJobName() + "'" : "";
String sortOrder = (Cli.isAscending()) ? "ASC" : "DESC";
String orderByClause = Cli.isRandom() ? " ORDER BY [Randomizer] " + sortOrder + ",[RecordID] " + sortOrder : " ORDER BY [RecordID] " + sortOrder;
String startingIdFilter = (Cli.getStartingId() != null) ? " AND [RecordId] > " + Cli.getStartingId() : "";
String driverQuery = "SELECT [RecordID], [Column1] AS [TrackingID], [Address]" + ", [Suite] AS [AptSuiteOther], [City], [Building2Key]"
+ ", [ST] AS [State], [ZIPCode]" + ", [BusinessName], [ContactLastName], [Suite]" + ", [Phone], [EmailAddress]"
+ " FROM [Project].[TestSet] WITH (READUNCOMMITTED)"
+ " INNER JOIN [Project].[State] sttable ON sttable.[ST] = UPPER([Project].[TestSet].[ST]) AND [TerritoryFlag] = 0" + " WHERE [BuildingKey] = 0 " + jobNameFilter
+ startingIdFilter + " AND (([FirstResponse] IS NULL AND ([Building2Key] IS NULL OR [Building2Key] = 0)) OR ([Building2Key] > 0 AND [SecondResponse] IS NULL)) " + orderByClause;
rs = stmt.executeQuery(driverQuery);
} catch (SQLException e1) {
logger.error("SQLException", e1);
}
try {
while (rs.next()) {
int recordId = rs.getInt("RecordID");
// Process data
numberProcessed++;
}
} catch (SQLException sqle) {
logger.error("SQLException", sqle);
}
I'm closing all the ResultSet, Connection and Statement in a finally statement at a different level also.
I'm not sure if I need to set the timeout to something higher, setFetchSize to something greater? Trap timeout and create ResultSet again?
Change logic to only pull one row at a time?
You'd have to profile your app to find out for sure, but I'm guessing that the "// Process data" part is the culprit. You're holding the connection open while process all of the rows.
I'd suggest that you read a batch of rows at a time, close the statement, and then process the batch. Then do a select for the next batch, rinse and repeat.
Selecting one row at a time would introduce a lot of overhead, so I wouldn't suggest doing that.
Also, make sure that you're using a connection pool, so that you don't actually have to build a new Connection each time. The pool will keep it open for you, and recycle it if it goes dead / times out.

Sql Syntax error unknown field list but looking for wrong field?

So I created the following function to write to a database:
public static void updateBuyer(String ID, String name, Location latlong) {
float lat = latlong.latitude;
float lon = latlong.longitude;
try {
// new com.mysql.jdbc.Driver();
Class.forName("com.mysql.jdbc.Driver").newInstance();
// conn =
// DriverManager.getConnection("jdbc:mysql://localhost:3306/testdatabase?user=testuser&password=testpassword");
conn = DriverManager.getConnection(connectionUrl, connectionUser,
connectionPassword);
stmt = conn.createStatement();
String sql = "UPDATE Buyer " + "SET latitude ="
+ Float.toString(lat) + " WHERE idBuyer in (" + ID + ")";
String sql2 = "UPDATE Buyer " + "SET longitude ="
+ Float.toString(lon) + " WHERE idBuyer in (" + ID + ")";
String sql3 = "UPDATE Buyer " + "SET Name =" + name
+ " WHERE idBuyer in (" + ID + ")";
stmt.executeUpdate(sql);
stmt.executeUpdate(sql2);
stmt.executeUpdate(sql3);
conn.close();
} catch (Exception e) {
System.err.println(e);
}
}
Lets say I passed the following parameters:
(12,craigs,location object)
Now when I run the function I get the following error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'craigs' in 'field list'
12 is the ID i retrieved from the databases earlier,
craigs is the random name I am trying to insert, and
location object is just a set of coordinates (lat,long)
Which leads me to think that it is looking for a field called "craigs" in the table for some reason, but why would it do that?
The problem is that you've got SQL like this:
UDPATE Buyer SET Name = craigs WHERE idBuer in (Whatever)
That's trying to copy the value from a column named "craigs".
Now you could just add apostrophes - but don't. Instead, use parameterized SQL with a prepared statement. That way you'll avoid SQL injection attacks, your code will be simpler, and you'll avoid unnecessary string conversions which can cause problems, particularly with date values.
Additionally, you only need a single statement, which can update all three columns:
String sql = "UPDATE Buyer SET Name=?, latitude=?, longitude=? WHERE idBuyer=?";
try (PreparedStatement statement = conn.prepareStatement(sql)) {
statement.setString(1, name);
statement.setFloat(2, lat);
statement.setFloat(3, lon);
statement.setString(4, ID);
statement.executeUpdate();
}
(Note that I've assumed you're actually only trying to update a single buyer - it's not clear why you were using IN at all. Also note that I'm using a try-with-resources statement, which will automatically close the statement afterwards.)
Additionally, I would *strongly *advise you to avoid just catching Exception. Catch SQLException if you must - but you'd actually probably be better letting it just propagate up the call stack.

Data does not get inserted into the table sometime

I have a table A. I insert data into table A through a user interface. Table A has an ID(primary key), which is generated using a sequence, and 16 other columns. One of the column is called cntrct_no.
When I try to insert data into the table through UI, it works fine the first time. I check the table A and all the data are there.
But when I try to insert the same data again without changing anything, it looks like the data is getting added to the table and I do not get any errors. But when I check table A, the data inserted the second time is not there.
If I try to insert the same data directly thorough SQL developer, the data gets inserted into the table.
The weird thing is if I just change the value of the cntrct_no in the UI and leave rest of the data same, the data gets inserted.
Can anyone please explain to me what could possibly cause this?
Not sure if this helps: stmt.executeUpdate(); returns 0 when the data is not inserted and a 1 when it's inserted.
public void writeToAudit(String contractNo, String tripNo,
String tripEffDate,
String tripDiscDate, String transpModeId, String userId,
String transType, AplLeg[] legs) {
final Session session = HibernateUtil.getSession();
Connection con = null;
con = session.connection();
PreparedStatement stmt = null;
PreparedStatement stmtSelId = null;
ResultSet rs = null;
long nextId = -1;
int i=0;
try {
for(i=0;i<legs.length;i++) {
String sqlNextId = "SELECT rpt_audit_transportation_seq.NEXTVAL as seqval FROM DUAL";
stmtSelId = con.prepareStatement(sqlNextId, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmtSelId.executeQuery();
rs.last();
final int rows = rs.getRow();
if (rows == 0){
nextId = -1;
}
rs.beforeFirst();
rs.next();
nextId = rs.getInt(1);
if(nextId==-1)
throw new SQLException("Cannot get next val from rpt_audit_transportation sequence.");
stmt = con.prepareStatement(WRITE_TO_AUDIT_DML);
stmt.setLong(1, nextId);
stmt.setString(2, userId.toUpperCase());
stmt.setString(3, transType);
stmt.setString(4, contractNo);
stmt.setString(5, tripNo);
stmt.setInt(6, Integer.parseInt(transpModeId));
stmt.setString(7, tripEffDate);
stmt.setString(8, tripDiscDate);
stmt.setLong(9, legs[i].getLegId().longValue());
int temp = stmt.executeUpdate();
con.commit();
}
stmt.close();
}
catch (Exception e) {
}
finally {
closeConnection(session, con, stmtSelId, rs);
}
}
THE SQL STATEMENT:
private static final String WRITE_TO_AUDIT_DML =
"INSERT INTO rpt_audit_transportation " +
"(audit_id, audit_date, audit_process, audit_userid, " +
"audit_trans_type, audit_route_no, audit_trip_no, " +
"audit_eff_dt, audit_disc_dt, audit_orig_facility_id, " +
"audit_dest_facility_id, audit_arvl_tm, audit_dprt_tm, " +
"audit_leg_seq_no, audit_freq_id, audit_trnsp_mode_id) " +
"(SELECT ?, " + // audit id
"SYSDATE, " +
"'TOPS_UI', " +
"?, " + // userId
"?, " +
"rte.cntrct_no, " +
"trp.trip_no, " +
"rte.cntrct_eff_dt, " +
"rte.cntrct_disc_dt, " +
"NVL(leg.orig_facility_id, trp.orig_fac_id), " +
"NVL(leg.dest_facility_id, trp.dest_fac_id), " +
"NVL(leg.arvl_tm, trp.arvl_tm), " +
"NVL(leg.dprt_tm, trp.dprt_tm), " +
"leg.leg_seq, " +
"trp.freq_id, " +
"rte.trnsp_mode_id " +
"FROM apl_contract rte, " +
"apl_trip trp, " +
"apl_leg leg " +
"WHERE rte.cntrct_no = ? " + // contract id
"AND trp.trip_no = ? " + // trip no
"AND rte.trnsp_mode_id = ? " + // transp mode id
"AND rte.cntrct_locked_ind = 'N' " +
"AND trp.trip_eff_dt = to_date(?,'MM/DD/YYYY') " + // trip eff date
"AND trp.trip_disc_dt = to_date(?,'MM/DD/YYYY') " + // trip disc date
"AND trp.cntrct_id = rte.cntrct_id " +
"AND leg.trip_id = trp.trip_id " +
"AND leg.leg_id = ?) ";
Looks like you're not inserting plain values, but a result of a select based on the parameters.
What you are using is an INSERT ... SELECT () clause, so if the SELECT part does not return any rows, the INSERT won't insert anything, and stmt.executeUpdate() will return 0. Find out why SELECT returns no rows.
This may be due some triggers saving stuff in other tables when you do the insert into rpt_audit_transportation, but it's just a guess.
The problem is that you have a catch that is swallowing your exceptions
catch (Exception e) {
}
That means that when the SQL statement throws an error, you're telling your code to catch the exception and ignore it. It is almost always an error to do that since, as you're discovering, it means that your code can fail to do what you expect with no way of letting you know that something failed. At a minimum, you would need to log the exception somewhere. In general, though, if you cannot fix whatever condition lead to the exception, you ought to re-raise the exception or simply not catch it in the first place.
My guess is that the second insert is violating some constraint defined on the table. But since your code is catching the exception and throwing it away, you're not being notified that there was a constraint violation nor is your code noting which constraint was violated.
When the cntrct_no is same you are getting an exception and you are supperessing that as told by #Justin Cave. This may be because you are having a unique constraint for that field and the DB throws an error and you are suppressing.
When cntrct_no is changed - obviously the constraint wont fail and for primary key since you are using the sequence it would have generated the next number and it happily gets inserted in the DB.
Don't ever suppress the exception. Do some thing in that block either rethrow as application specific exception or convert to error code and propagate that to the front end.

Categories