Im trying to make a dynamic Delete Query.
What im basically trying to do is first grab the name of the first column in any table (the primary key). Then i use that in Another Query to delete from that table though i get a nullpointerexception?
Ohh and the primary key is not an INT like 1,2,3,4,5 etc.. it's formed up as S1,S2,S3,S4,S5 etc and has the type TEXT.
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:test.db");
c.setAutoCommit(true);
System.out.println("Opened database successfully");
ResultSet rs = stmt.executeQuery("SELECT * FROM "+tablename);
ResultSetMetaData rsmd = rs.getMetaData();
FirstColumn = rsmd.getColumnName(1);
String query = "DELETE FROM "+tablename+" WHERE " +FirstColumn+ " = " +row;
stmt = c.createStatement();
stmt.executeUpdate(query);
stmt.close();
c.close();
I am going to assume that all the variables you are using have been initialized.
I added single quotes around the FirstColumn name.
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:test.db");
c.setAutoCommit(true);
System.out.println("Opened database successfully");
ResultSet rs = stmt.executeQuery("SELECT * FROM "+tablename);
ResultSetMetaData rsmd = rs.getMetaData();
FirstColumn = rsmd.getColumnName(1);
String query = "DELETE FROM "+ tablename +" WHERE " + FirstColumn + " = '" + row + "'";
stmt = c.createStatement();
stmt.executeUpdate(query);
stmt.close();
c.close();
If you are still getting an error you should try printing out your row name and see what it prints out.
Edit: Since you are new stylistically it's preferable to add a single space when using operators to improve code readability. For example 1+3+x+34 is a lot harder to read than 1 + 3 + x + 34. Granted there is no "wrong" code style but improving code readability is always a plus.
Initialize your stmt object...
stmt = c.createStatement();
before executing the query.
Related
I wrote code to run multiple statement in single connection. The first statement will retrieve IDs to be looped and used by the second statement then get the desired output. As example:
String sql1 = "SELECT ID FROM __TestParent WHERE Status = 'S'";
try (
Connection conn = DbConnector.getConnection();
Statement s = conn.createStatement();
Statement s2 = conn.createStatement();
ResultSet rs = s.executeQuery(sql1)
) {
while(rs.next()) {
String id = String.valueOf(rs.getInt("ID"));
String sql2 = "SELECT Description FROM __TestChild WHERE FK = " + id;
try (
ResultSet rs2 = s2.executeQuery(sql2)
) {
while(rs2.next())
Util.printLog("INFO",rs2.getString("Description"));
}catch(SQLTimeoutException sqltoex){
Util.printLog("SEVERE",sqltoex);
}catch(SQLException sqlex){
Util.printLog("SEVERE",sqlex);
}
}
}catch(SQLTimeoutException sqltoex){
Util.printLog("SEVERE",sqltoex);
}catch(SQLException sqlex){
Util.printLog("SEVERE",sqlex);
}
Util.printLog method is to print the message in the desired format
The code run perfectly fine and the output was as expected. What I want to know is:
Is this the right way to do it, or is/are there better way to write the code.
Is there anything that I need to be aware of? Because I seems cannot find anything about this use case other than this link Multiple-statements-single-connection from CodeRanch which is 16-year-old thread and I'm not quite clear other than driver support.
Thanks.
You can actually do what you want using a single query and result set:
SELECT c.Description
FROM __TestChild c
INNER JOIN __TestParent p
ON c.FK = p.ID
WHERE p.Status = 'S';
Code:
String sql = "SELECT c.Description FROM __TestChild c ";
sql += " INNER JOIN __TestParent p ON c.FK = p.ID ";
sql += "WHERE p.Status = 'S'";
try (
Connection conn = DbConnector.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(sql)
) {
while(rs.next()) {
Util.printLog("INFO", rs.getString("Description"));
}
} catch(SQLTimeoutException sqltoex) {
Util.printLog("SEVERE",sqltoex);
} catch(SQLException sqlex) {
Util.printLog("SEVERE",sqlex);
}
I want to show the Column numbers of a table but it always shows the number 1. I have written the code below:
Class.forName(JDBC_DRIVER);
java.sql.Connection con=DriverManager.getConnection(DB_URL,USER,PASS);
try (Statement stmt = (Statement) con.createStatement()) {
String sql;
sql = "SELECT count(*) FROM information_schema.columns WHERE
table_name=\"my_b\"";
try (
ResultSet rs = stmt.executeQuery(sql)) {
int columCount = rs.getMetaData().getColumnCount();
System.out.println("Column number is: "+columCount);
}
stmt.close();
con.close();
Where is the error ?
First, you haven't needed Class.forName to load your JDBC drivers in a long time. Second, you are selecting a value but you are reading metadata. Third, when using try-with-resources you don't need explicit close calls (and your Connection should be closed in a finally, for example). Finally, use PreparedStatement and bind parameters. Like,
java.sql.Connection con = DriverManager.getConnection(DB_URL, USER, PASS);
String query = "SELECT count(*) FROM information_schema.columns WHERE table_name=?";
try (PreparedStatement stmt = con.prepareStatement(query)) {
stmt.setString(1, "my_b");
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
int columCount = rs.getInt(1);
System.out.println("Column number is: " + columCount);
} else {
System.out.println("No rows");
}
}
} finally {
con.close();
}
You are not retrieving the result of the query, instead you are asking the result set metadata how many columns the result set has. And as your query only produce a single column (ie COUNT(*)), the result of ResultSetMetaData.getColumnCount() is 1, and that value is correct.
If you want to get the result of the query, you need to get it from the result set:
try (ResultSet rs = stmt.executeQuery(sql)) {
if (rs.next()) {
int columnsNumber = rs.getInt(1);
System.out.println("Column number is: "+columnsNumber );
}
}
The problem is that ResultSet.getColumnCount returns the number of columns in the query's result set, not the number of columns in a table.
If you are trying to get a count of columns on a table, the query you have is correct. You just need to retrieve the result of the query, rather than its metadata.
String sql = "SELECT count(*) FROM information_schema.columns WHERE table_name=\"my_b\"";
try (
ResultSet rs = stmt.executeQuery(sql));
rs.next();
int columCount = rs.getInt(1);
System.out.println("Column number is: " + columCount);
}
Class.forName(JDBC_DRIVER);
java.sql.Connection con=DriverManager.getConnection(DB_URL,USER,PASS);
try (Statement stmt = (Statement) con.createStatement()) {
String sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = 'database_name' AND table_name = 'table_name'"
try (
ResultSet rs = stmt.executeQuery(sql)) {
//int columCount = rs.getMetaData().getColumnCount();
ResultSetMetaData rsmd = rs.getMetaData();
int columnsNumber = rsmd.getColumnCount();
System.out.println("Column number is: "+columnsNumber );
}
stmt.close();
con.close();
Try SELECT * FROM information_schema.columns WHERE table_name=\"my_b\"
Just omit the count(*) since this returns a single result, while you are looking for all columns.
I'm trying to send in ORDER table last ID from CUSTOMER and all IDs from PRODUCT tables. In "idproduct"(ORDER table) should appears all IDs with white spaces between them. I used here rs.next() twice and I know that it isthe reason why error appears, but how can I handle it? Here is a code:
List<String> IDproducts = new ArrayList<>();
Connection conn = db.getConnect();
PreparedStatement pst = conn.prepareStatement("SELECT * FROM `onlineshop`.`customer`");
ResultSet rs = pst.executeQuery();
while (rs.next()){
rs.getString(1);
}
Connection conn1 = db.getConnect();
PreparedStatement pst1 = conn1.prepareStatement("SELECT * FROM `onlineshop`.`product`");
ResultSet rs1 = pst1.executeQuery();
while (rs1.next()){
IDproducts.add(rs1.getString(1));
}
db.Query("INSERT INTO `onlineshop`.`order` (`idcustomer`, `idproduct`)
VALUES ('"+rs.getString(1)+"','" + IDproducts + ")");
error:
java.sql.SQLException: After end of result set
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:959)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:898)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:887)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:862)
com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:790)
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5244)
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5167)
I know that I can count the entries in SQL with
SELECT COUNT (*) FROM table
but I don't know how do perfom that in Java.
This is my Code to perform a SQL command.
Statement stmt = conn.createStatement();
stmt.executeQuery("SELECT COUNT (*) FROM table")
Result:
rs2: org.h2.result.LocalResult#41cf3f60 columns: 1 rows: 1 pos: -1
But it should return > 20
My code:
Connection conn = null;
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection(
"jdbc:h2:" + Environment.getExternalStorageDirectory()
+ "/sorter/database", "", "");
Statement stmt = conn.createStatement();
Toast.makeText(context,
String.valueOf(stmt.executeQuery(sql)),
Toast.LENGTH_LONG).show();
conn.close();
if (conn != null)
conn.close();
What you see is the toString() method of the ResultSet you never actually retrieve a value from the result.
executeQuery returns a ResultSet that you use to get the actual data. It is not the result of the query directly (think about how this should work when returning multiple rows and multiple columns)
You need to do something like this:
ResultSet rs = stmt.executeQuery(sql);
int count = -1;
if (rs.next())
{
count = rs.getInt(1);
}
This is all nicely explained in the JDBC Tutorial:
http://docs.oracle.com/javase/6/docs/technotes/guides/jdbc/getstart/resultset.html#998035
Another possibility is
ResultSet rs=conn.prepareStatement("SELECT COUNT(*) FROM table").executeQuery();
if(rs.next()) sysout(rs.getInt(1));
Please help me out, I am trying to update the value of one column in a rowset but I am continously getting an exception..that rowset is not write enabled.
I searched a lot but didn't find a way to make the rowset write enabled.
Mentioning below the code that I am using and the following exception:
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:orcl", uname, pwd);
String query = "select * from " + table;
PreparedStatement preparedStatement = conn.prepareStatement(query);
ResultSet rset = preparedStatement.executeQuery();
OracleCachedRowSet oracleCachedRowSet = new OracleCachedRowSet();
oracleCachedRowSet.populate(rset);
ResultSetMetaData resultSetMetaData = oracleCachedRowSet.getMetaData();
int numberOfColumns = resultSetMetaData.getColumnCount();
while (oracleCachedRowSet.next()) {
oracleCachedRowSet.updateBigDecimal(1, new BigDecimal(99));
oracleCachedRowSet.updateRow();
oracleCachedRowSet.acceptChanges();
for (int i = 1; i <= numberOfColumns; i++) {
System.out.print(oracleCachedRowSet.getString(i) + " ");
}
}
}
Exception coming on executing the above code :
java.sql.SQLException: The RowSet is not write enabled
at oracle.jdbc.rowset.OracleCachedRowSet.checkColumnIndex(OracleCachedRowSet.java:912)
at oracle.jdbc.rowset.OracleCachedRowSet.updateObject(OracleCachedRowSet.java:5931)
at oracle.jdbc.rowset.OracleCachedRowSet.updateBigDecimal(OracleCachedRowSet.java:6430)
at Test.getDBConnection(Test.java:86)
at Test.main(Test.java:37)
Try setting:
oracleCachedRowSet.setReadOnly(false);
Javadoc for ResultSet tells us
A default ResultSet object is not updatable and has a cursor that moves forward only.
I guess, the message of your exception is related to that issue. The javaDoc provides an example how to create a scrollable and updateable result set:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable