Submitting a query from SQLiteStudio returns the expected result from a View.
However, when the same query is sent from my program in java, the result is different for some queries.
ie: SELECT Rev FROM PartRevs WHERE PartNumber = '800111'
This returns the expected result of "B" when executed within SQLiteStudio. However, then the same query is executed from JAVA, it returns "A". Only one result is returned with both queries.
This does not happen consistently. Most queries work, but it occasionally does not work.
The 'Rev' or Revision of a given part is pulled from another table called 'ECO_TDA_Linewise'. Each time a new revision is released for a given part, a new line is added with increasing index numbers.
I believe the problem comes from the way the 'PartRevs' view works. Of the many other tables and queries, this is the only one that has an issue.
Here are the code blocks that interact with the database:
public String GetRevision(String PartNumber) {
String sqlStatement = "SELECT Rev FROM PartRevs WHERE PartNumber = '" + PartNumber + "'";
return getDatabaseResult(sqlStatement, "Rev");
}
public String getDatabaseResult(String sqlStatement, String Column) {
String result = "";
try (Connection conn = FulfillmentWorkorders.connect();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sqlStatement)) {
result = rs.getString(Column);
conn.close();
} catch (SQLException e) {
System.out.println("\"" + sqlStatement + "\" throws exception: " + e.getMessage());
}
return result;
}
Related
I have a class called "Database" that is working perfectly well. It queries a database and returns the results as a string. When I call the class from my "Test" class it returns the results string and I can print it with System.out.println().
I'm trying to use this class on a JSP page using the same two lines of code to instantiate the class and get the string output. When I try to output on the JSP page I get nothing. What am I doing wrong? I'm completely stumped.
Class Code:
public class Database {
static String[][] reservations = new String[7][20];
public Database (String theDate) {
String url = "jdbc:mysql://myurl.com:3306/";
String driver = "com.mysql.cj.jdbc.Driver";
String user = "myusername";
String pass = "mypassword";
String db = "class";
String options = "?useSSL=false";
try (Connection conn = DriverManager.getConnection(url + db + options, user, pass);
Statement statement = conn.createStatement()) {
String query = "select reservation.first, reservation.last, startday, numberofdays, guides.first as guidefirst, guides.last as guidelast, locations.location from reservation left join guides on reservation.guide = idguides left join locations on reservation.location = idlocations where StartDay >= " + theDate;
ResultSet rs = statement.executeQuery(query);
int row = 0;
while (rs.next()) {
reservations[0][row] = rs.getString("first");
reservations[1][row] = rs.getString("last");
row++;
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public String getStringRes () {
String returnString = "";
for(int i=0; i<20; i++) {
if (reservations[0][i] != null) {
returnString += i + " " + reservations[0][i];
returnString += " " + reservations[1][i] + "\n";
}
}
return returnString;
} }
JSP Code:
<%# page import="mypackage.Database" %>
<%
Database db = new Database("2015-07-01");
String str = db.getStringRes();
%>
<%= str %>
Your code contains 3 mistakes.
The most problematic
} catch (SQLException e) {
e.printStackTrace();
}
Don't ever do that. Go into your IDE settings and eliminate this template. It should be throw new RuntimeException("Unhandled", e); instead.
Here's what happened: Your SQL statement is erroneous (in two ways, even). This causes an exception. Your code handles this by ignoring it (it's printed, but, your code finishes normally). Hence, the string result remains blank (because it starts out that way and the code that is supposed to give it its real value never ran, due to the exception that you ignored).
Your SQL is broken.
The actual explanation is that date literals need to be in quotes, in SQL. Yours is not.
But that's not how you pass parameters into SQL.
The bigger issue is that passing any value like this into an SQL means your machine will be hacked in a matter of days. That's called 'SQL injection'. You don't want it. The solution is preparedstatements, where you let the JDBC driver and/or the database take care of escaping or otherwise passing string data without the SQL db engine trying to interpret it as SQL (Because, obviously, letting arbitrary users type stuff in that your DB engine then treats as SQL means you're just waiting for someone to construct some SQL such that your db engine ends up executing DROP TABLE reservation CASCADE; EXECUTE 'FORMAT C: /Y'; --.
Minor style nit
Doing business logic in constructors is a bad idea. The query should be done from getStringRes, most likely. That's also a bit of a crazy method name. Not very informative.
Which gets us to...
try (Connection conn = DriverManager.getConnection(url + db + options, user, pass);
PreparedStatement statement = conn.prepareStatement("SELECT reservation.first, .... FROM .... WHERE StartDay >= ?")) {
statement.setString(1, theDate);
try (ResultSet rs = statement.executeQuery()) {
...
}
} catch (SQLException e) {
throw new RuntimeException("unhandled", e);
}
This is the code where I'm trying to execute a second query on the resultSet of my first lengthy query. I need to upload this
data somewhere.
Is it the right thing to do?
Or is there a better approach apart from querying the database again?
public String createQuery() throws SQLException {
StringBuilder Query = new StringBuilder();
try {
Query.append(" SELECT ...... ")
} catch (Exception e) {
e.printStackTrace();
}
return Query.toString();
}
private void openPreparedStatements() throws SQLException {
myQuery = createQuery();
try {
QueryStatement = dbConnection.prepareStatement(myQuery);
} catch (SQLException e) {
e.printStackTrace();
return;
}
}
public ResultSet selectData(String timestamp) throws SQLException {
openConnection();
ResultSet result = null;
ResultSet rs_new=null;
try {
result = QueryStatement.executeQuery();
while (result.next()) {
String query = "SELECT * FROM " + result + " WHERE " + "ID" + " =" + "ABC";
rs_new =QueryStatementNew.executeQuery(query);
System.out.print(rs_new);
}
} catch (SQLException e) {
LOGGER.info("Exception", e);
}
return result;
}
Instead of running two separate queries (when you don't need the intermediate one) you can combine them.
For example you can do:
SELECT *
FROM (
-- first query here
) x
WHERE ID = 'ABC'
You cannot use two statement objects within one database connection. So you can either open another database connection and execute the second statement in the 2nd connection, or iterate through the resultset from first statement and store the value you need (e.g. in an array/collection) then close that statement and run the second one, this time retrieving the value from the array/collection you saved them in. Refer to Java generating query from resultSet and executing the new query
Make Db2 keep your intermediate result set in a Global Temporary Table, if you have an ability to use it, and you application uses the same database connection session.
DECLARE GLOBAL TEMPORARY TABLE SESSION.TMP_RES AS
(
SELECT ID, ... -- Your first lengthy query text goes here
) WITH DATA WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED;
You may send the result of subsequent SELECT ... FROM SESSION.TMP_RES to FTP, and the result of SELECT * FROM SESSION.TMP_RES WHERE ID = 'ABC' to elastic.
This is driving me mad because I cannot make any sense of it. I am executing the following code:
nameString = jcbClientList.getItemAt(jcbClientList.getSelectedIndex());
System.out.println(" Name String = " + nameString );
sql = "SELECT * FROM clients WHERE Name = \'" + nameString + "\'";
System.out.println(sql);
try {
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
while( rs.next()) {
clientID = rs.getInt(1);
}
}
catch(SQLException se) {
msg = "Problem getting client ID from DB \n" + se.getLocalizedMessage();
System.out.println(msg);
JOptionPane.showMessageDialog(null, msg);
}
The SQL string be built is correct. I have checked this by taking the System.out.println(sql) output of the string and pasting it into other code and it work perfectly. However, in this context I am getting an exception:
Invalid cursor state - no current row.
Even if I change the sql to be 'SELECT * FROM clients' which should return 20 rows and does elsewhere in the application, it still gives the same error. The database being addressed is an embedded Derby DB.
I seem to recall having run into specific JDBC drivers that did not properly implement the part that says " A ResultSet cursor is initially positioned before the first row ". I got around it by first doing a first() (or beforeFirst()) call and only then start invoking next().
Basically, I have to show a list with the data from a database table [that part is working] and afterwards I have to show the highest Date [a date variable in the table]. The second part is not working no matter what I do.
Here's the code
try {
String SQL = "SELECT * FROM tb_rafael";
ResultSet rs = BD.consultar(SQL);
String tab = "";
int numReg = 0;
while (rs.next()) {
tab+="<TR>";
tab+="<TD>" + rs.getString("nme_rafael") + "</TD>";
tab+="<TD>" + rs.getString("dta_rafael") + "</TD>";
tab+="</TR>";
numReg++;
//mDat = rs2.getString("dta_rafael");
}
rs.close();
dados.put("DADOS", tab);
dados.put("NUM_REG", String.valueOf(numReg));
//Pegar Data Maior
String SQL2 = "SELECT MAX(dta_rafael) FROM tb_rafael";
ResultSet rs2 = BD.consultar(SQL2);
String mDat = "";
//while(rs2.next()){
mDat = rs2.getString("dta_rafael");
//}
rs2.close();
dados.put("MDA", mDat);
} catch (Exception ex) {
dados.put("MSG", "Erro: " + ex.getMessage());
}
What you want to look at is past the commentary line "Pegar Data Maior". That's the part that is not working. I've tried adding a while, using a different ResultSet, using the same ResultSet and none of those worked. I know it's not an issue with the SQL query since I tested it with the workbench and it returned me the data I want.
To be more specific, I don't get an error message or anything, the dados.put simply does not work and I get just this:
How the HTML code looks:
The data should show up where the {MDA} is. Anyone have any ideas?
The query SELECT MAX(dta_rafael) FROM tb_rafael may not return a column name, which you later try to retrieve, rs2.getString("dta_rafael");
I'd change the query to SELECT MAX(dta_rafael) AS Max_date..., and reference to MAX_date thereafter.
I am attempting to pull results from an Oracle database. I have written a query that is correct, and produces accurate results when issued manually in sqlplus. Furthermore, the code works as expected when when the query matches only one row (In other words, when the ResultSet has only one row, everything works). However, when more than one row match the query, the ResultSet returned by the Oracle JDBC is empty.
public Component[] getAllComponents(int typeId, int osId) throws SQLException
{
String query= "SELECT c.component_id, c.component_name, c.component_version, c.type_id, c.post_download_instructions, "
+ "o.os_id, o.os_name, o.description AS os_description, "
+ "i.file_location, i.release_date, i.patch_number, i.file_id, "
+ "i.description AS i_description "
+ "FROM components c, installation_files i, operating_systems o "
+ "WHERE c.type_id = ? "
+ "AND i.os_id = ? "
+ "AND c.component_id = i.component_id "
+ "AND i.os_id = o.os_id";
ResultSet results = null;
PreparedStatement stmt = null;
ArrayList<Component> found = new ArrayList<Component>();
try {
stmt = dbConn.prepareStatement(query); //dbConn is member variable
stmt.setInt(1, typeId);
stmt.setInt(2, osId);
results = stmt.executeQuery();
while(results.next()){
//Some logic
}
} finally {
if(results != null) results.close();
if(stmt != null) stmt.close();
dbConn.close();
}
//More Code
//etc. etc.
Inspecting the ResultSet shows that calling ResultSet.next() never produces true when the fetched results should contain more than one row. However, issuing the query manually does produce results, and when only one row is returned, everything works fine. Does anyone know what's going on? I'm using Oracle's ojdbc6.jar.
Thanks!
Before that query you can check if there really are some components with COUNT(*) instead of all fields. Then run your query only if COUNT(*) is one or more.