Is possible to merge my following queries into one? I'm using mysql as my database.
String qry = "SELECT id FROM customers WHERE completed=false AND server=?";
ps = connection.prepareStatement(qry);
ps.setString(1,getServerId());
rs = ps.executeQuery();
final Set<Long> ids = new HashSet<>();
while (rs.next()) {
ids.add(rs.getLong(1));
}
qry = "";
for (long l : ids) {
qry += "UPDATE customers SET completed=true WHERE id = "+l+"; ";
}
... execute query, close streams, and do some application logic with ids from database...
You can just
UPDATE customers SET completed=true WHERE completed=false AND server=?
Edit: You provided the information saying you need to actually use the Ids.
Select normally then build a string in the format MySql understands as a "list", it will certainly be faster than multiple update queries and will cost less bytes to send over the network. Here is the snippet:
String qry = "SELECT id FROM customers WHERE completed=false AND server=?";
ps = connection.prepareStatement(qry);
ps.setString(1,getServerId());
rs = ps.executeQuery();
final Set<Long> ids = new HashSet<>();
while (rs.next()) {
ids.add(rs.getLong(1));
}
qry = "";
if(ids.size()>0) {
StringBuilder idsAsString = new StringBuilder();
for(int i = 0; i < ids.size(); i++) {
idsAsString.append(ids.get(i));
if(i < ids.size()-1)
idsAsString.append(",");
}
qry = "UPDATE customers SET completed=true WHERE id IN ("+idsAsString+"); ";
}
instead of building multiple UPDATE statements in a for loop.
Related
I need to write an update function where its content is different based on what parameters are passed, e.g. if I have updateBook(int id, String title, String author, int pages), I have to do something like:
String sql;
if((!title.equals("null"))&&(!author.equals("null"))&&(pages>0)))
sql = "UPDATE book SET title='"+title+"', author='"+author+"', pages="+pages;
else if(((!title.equals("null"))&&(!author.equals("null")))
sql = "UPDATE book SET title='"+title+"', author='"+author+"'";
else if(((!title.equals("null"))&&(pages>0)))
sql = "UPDATE book SET title='"+title+"', pages="+pages;
... //and so on
sql = sql + " WHERE bookid="+id+";";
The more fields I have in my table, the more checks I have to do, which is uncomfortable, and requires me to write a lot of code.
Also, doing something like:
sql = "UPDATE book SET ";
if(!title.equals("null"))
sql = sql +"title='"+title+"',";
if(!author.equals("null"))
sql = sql+"author='"+author+"',";
if(pages>0)
sql = sql+"pages="+pages";
sql = sql + ";";
can't work since the unwanted commas cause statement errors.
You can see as well that if I have something like 6, 7, 8 etc field the checks start to get too many, and I can't also do more separated update statements as if something goes wrong I would need to rollback any query that has been done in that function.
Is there any way round to get a custom update statement having to write few code?
Firstly, use a PreparedStatement.
I would do it something like the following.
List<Object> params = new ArrayList<>();
StringBuilder sql = new StringBuilder();
if(!title.equals("null")) {
sql.append("title = ?");
params.add(title);
}
if(!author.equals("null")) {
if (sql.length() > 0) {
sql.append(", ");
}
sql.append("author = ?");
params.add(author);
}
if(pages>0) {
if (sql.length() > 0) {
sql.append(", ");
}
sql.append("pages = ?");
params.add(pages);
}
if (sql.length() > 0) {
sql.insert(0, "UPDATE book SET ");
sql.append(" WHERE bookid=?");
java.sql.Connection conn = // however you obtain it
java.sql.PreparedStatement ps = conn.prepareStatement(sql.toString());
for (int i = 0; i < params.size(); i++) {
ps.setObject(i + 1, params.get(i));
}
ps.executeUpdate();
}
First I am going to try using query to retrieve the int min_stock single cell using the item description. Then put that value into a variable. I want to be able to have the variable minStock to be equal to a number. I want to use it to make operations in my program.
PreparedStatement cm = con.prepareStatement(checkMinimumStock);
ResultSet minS = cm.executeQuery("SELECT min_stock FROM items WHERE item_description = '"+item+"'");
int minStock = minS.getInt("min_stock");```
you are choose wrong way to use PrepareStatment.
you have two option to do :
1:
String sql = "SELECT min_stock FROM items WHERE item_description = ?";
PreparedStatement cm = con.prepareStatement(sql);
cm.setString(1, item);
ResultSet rs = cm.executeQuery();
2:
String sql = "SELECT min_stock FROM items WHERE item_description = '" + item + "'";
ResultSet rs = con.createStatement().executeQuery(sql);
and then
if (rs.next())
int minStock = rs.getInt("min_stock");
else
//not found any match row in DB table
Try this
String checkMinimumStock = "SELECT min_stock FROM items WHERE item_description = ? ";
PreparedStatement cm = con.prepareStatement(checkMinimumStock);
cm.setString(1,item);
ResultSet minS = cm.executeQuery();
if(minS.next()){
int minStock = rs.getInt("min_stock");
}
String checkMinimumStock = "SELECT min_stock FROM items WHERE item_description = ? ";
Forgot to add this in the beginning of the code!
I want to retrieve a particular column from the database. For a simple Select statement, I can able to able to retrieve a column like below
public String getDbColumnValue(String tableName, String columnName, String applicationNumber) {
String columnValue = null;
try {
PreparedStatement ps = null;
String query = "SELECT " + columnName + " FROM " + tableName +
" WHERE ApplicationNumber = ?;";
ps = conn.prepareStatement(query);
ps.setString(1, applicationNumber);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
columnValue = rs.getString(columnName);
return columnValue;
}
}
catch (Exception ex) {
}
return columnValue;
}
But, I'm using alias in my query like below. And this query works fine. How to use this in Java to retrieve a particular column
select S.StatusDesc from application A, StatusMaster S
where A.StatusMasterId = S.StatusMasterId and A.ApplicationNumber = '100041702404'
Any help would be greatly appreciated!
I think you are confusing simple aliases, which are used for table names, with the aliases used for column names. To solve your problem, you can just alias each column you want to select with a unique name, i.e. use this query:
select S.StatusDesc as sc
from application A
inner join StatusMaster S
on A.StatusMasterId = S.StatusMasterId and
A.ApplicationNumber = '100041702404'
Then use the following code and look for your aliased column sc in the result set.
PreparedStatement ps = null;
String query = "select S.StatusDesc as sc ";
query += "from application A ";
query += "inner join StatusMaster S ";
query += "on A.StatusMasterId = S.StatusMasterId ";
query += "and A.ApplicationNumber = ?";
ps = conn.prepareStatement(query);
ps.setString(1, applicationNumber);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
columnValue = rs.getString("sc");
return columnValue;
}
Note: I refactored your query to use an explicit inner join instead of joining using the where clause. This is usually considered the better way to write a query.
If I have a search module which has the following:
search box, dropdown 1, dropdown 2.
And I have a query like this:
SELECT * FROM MY_TABLE where q1 = 'searchBox' AND q2 = 'dropdown1' AND q3 = 'dropdown2'
How can I make that query dynamic depending on user filter, so if the user only fills the search box, the query will be:
SELECT * FROM MY_TABLE where q1 = 'searchBox'
If the user fills search box and dropdown1, the query will be:
SELECT * FROM MY_TABLE where q1 = 'searchBox' AND q2 = 'dropdown1'
and if the user doesn't fill anything, the query will be:
SELECT * FROM MY_TABLE
I am using Java.
There are frameworks that can help with this:
QueryDSL
jOOQ
Squiggle
Hibernate
If you'd like to create a quick and simple solution, you can do something like the following:
List<String> params = new ArrayList<>();
StringBuilder sb = new StringBuilder();
sb.append("SELECT * FROM MY_TABLE WHERE 1 = 1");
if (searchBox != null) {
sb.append(" AND q1 = ?");
params.add(searchBox);
}
if (dropdown1 != null) {
sb.append(" AND q2 = ?");
params.add(dropdown1);
}
if (dropdown2 != null) {
sb.append(" AND q3 = ?");
params.add(dropdown2);
}
PreparedStatement preparedStatement = connection.prepareStatement(sb.toString());
for (int i = 1; i <= params.size(); i++) {
preparedStatement.setString(i, params.get(i));
}
ResultSet resultSet = preparedStatement.executeQuery();
To improve upon the code provided by #blacktide
PreparedStatement preparedStatement = connection.prepareStatement(sb.toString());
for (int i = 1; i <= params.size(); i++) {
preparedStatement.setString(i, params.get(i));
}
You would instead want the line within the for loop to be
preparedStatement.setString(i, params.get(i-1));
Since arrays start at 0, we'd want to grab that zeroth index to set the first value added to the list to the first value to be updated in the SQL string. Otherwise you would grab the second value within params which would not be the intended value.
I want the return row_number press the Variable Model class:
Whereas the PreparedStatament in the examples I exploreri, rferencia the column name. row_number is not a native or physical column of the table. How to make the values dete method are returned as if they were an actual physical table column. Nor would it be interesting to create a new column in the table to just store these values. I also do not intend to use triggers to return these values. It can be done this way is without error in the code below.
final StringBuffer lSql = new StringBuffer();
lSql.append("SELECT ");
lSql.append(" TABLE_NAME.ROW_NUMBER() OVER (ORDER BY COLUMN_DAY) ");
lSql.append("FROM ...");
// ...
final List<classModel> listData = new ArrayList<classModel>();
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
try{
conn = getConnection1();
stmt = conn.prepareStatement(lSql.toString());
int count = 1;
//stmt.setLong(count++, classModelParameterThisFunctionDAO.getVarColumnSequence());
//...
rset = stmt.executeQuery(); // ERROR THIS LINE NI DEBUG
while(rset.nex()){
final classModel lClassModel = new classModel();
lClassModel.setColumnSequence(rset.getInt("ROW_NUMBER() OVER (ORDER BY COLUMN_DAY)")); //error in this line
listData.add(lClassModel);
lSql.append("SELECT ");
lSql.append(" TABLE_NAME.ROW_NUMBER() OVER (ORDER BY COLUMN_DAY) as RRN ");
lSql.append("FROM ...")
.
.
.
lClassModel.setColumnSequence(rset.getInt("RRN"));