I need to create a room database query dynamically because I have lots of fields for UPDATE in the database.
If I used like below method then it works, but I have lots of fields that's why I can't create a separate UPDATE method like this.
#Query("UPDATE PROCEDUREMODEL SET patient_in_time = :val WHERE procedure_sr_number LIKE :sr")
void updateP(String val, String sr);
Now I try below but it does not work.
In DAO class I created this
#RawQuery
ProcedureModel updateProcedure(SupportSQLiteQuery supportSQLiteQuery);
And use like this
public static void updateProcedure(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
SupportSQLiteQuery supportSQLiteQuery = new SimpleSQLiteQuery(s);
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(supportSQLiteQuery);
});
thread.start();
}
I want to run the UPDATE query at runtime in Room database.
I believe that your issue is with the SQL being passed:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
As the value val is non-numeric, because of the :'s (which you probably don't want), likewise for the id (if not numeric) the values should be enclosed in single quotes.
So using:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = ':" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
would work. Although you very likely don't want the : as part of the value so you very likely want:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = '" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
Saying that it is not recommended to apply literal values via string concatenation but to utilise parameter binding. This protects against SQL injection. As such you may wish to consider the following version:-
public static void updateProcedureBetter(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + "=? WHERE procedure_sr_number LIKE ?";
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(new SimpleSQLiteQuery(s,new Object[]{val,id}));
});
thread.start();
}
notice the ?'s in the SQL these being replaced by the objects in the Object[], the values being properly enclosed by SQLite parameter binding.
the replacement is on a 1 by/for 1 basis (first ? replace by first object in array, 2nd ? by second object ....)
note also that the intermediate supportSQLiteQuery object has been done away with.
component names (tables, columns etc) typically cannot be bound/changed so the column name has to be concatenated.
I am trying to execute a select query from Java, the tricky part is that both the condition and the column have a String with spaces :
String query = "select rule_name "+
" from rules " +
" where rule_name = " m_rule; //rule_name = str tf //m_rule = str tf
So the query output :
select rule_name
from rules
where rule_name = str tf
The error code - ORA-00920 - I belive it is because of the spaces.
Is there any way to fix this?
The error that you are facing basically means :
ORA-00920: invalid relational operator
This is the blank that is causing the issue. Your Java code should enclose the conditional parameter in quotes:
String query = "select rule_name "+
" from rules " +
" where rule_name = '" + m_rule + "'";
Hope this will help!
When I concatenate a character namely tid
to this string in Java. I will get
where sc.CategoryCode = C
But I actually need
where sc.CategoryCode = 'C'
when I add a single quote both on the start
and on the end side of tid
like
where sc.CategoryCode = '" + tid + "'";
I'll get
where sc.CategoryCode = 'C"
And it seems very strange.
Thanks
Jack
String str = "select sc.* from SubCategory sc"
+ " where sc.CategoryCode = " + tid;
You shouldn't build up your SQL like this - you should use parameterized SQL instead:
// TODO: Closing the statement etc
String sql = "select sc.* from SubCategory sc where sc.CategoryCode = ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(tid); // Or statement.setString(String.valueOf(tid))
ResultSet results = statement.executeQuery();
Reasons for using parameterized SQL:
Avoiding SQL injection attacks
Avoiding unnecessary (and potentially problematic) conversions, particularly with dates/times
Keeping your code (the SQL) separate from the data (the parameters), which aids readability
I don't know if you are working with jdbc template... i post you an example.
select :
private static final String SELECT_SANCIONS_GIM = "SELECT * " + "FROM "
+ Constants.T_GPT_V_DETALL_SANCIO_GIM + " WHERE "
+ Constants.EXP_ID_ENS + " =:idEns" + " AND " + Constants.EXP_ANY_EXP
+ " =:anyExp" + " AND " + Constants.EXP_NUM_EXP + " =:numExp" + " AND "
+ Constants.ACRONIM_EXP + " =:acr";
//=:variable
I use Stringbuilder, take a look:
StringBuilder sql = new StringBuilder();
sql.append(SELECT_SANCIONS_GIM);
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("idEns",clauExpedient.getIdEns() );
parameters.addValue("anyExp",clauExpedient.getAnyExp());
parameters.addValue("numExp",clauExpedient.getNumExp() );
parameters.addValue("acr", clauExpedient.getAcrProcediment());
I hope it helps.
So i just wrote down this SQL query and i am trying to capture the value of rest_id in query.list(). However, this is giving the value as [1] . I want just 1 without the braces. How do i do it? Please check the code below for reference:
String sql1 = "select rest_id from rest_details where rest_name = '" + nameclicked + "' and rest_location = '" +locclicked + "'" ;
SQLQuery query1 = session.createSQLQuery(sql1);
System.out.println("sql1 " + query1.list());
Use below code to get the element inside list:
System.out.println("sql1 " + query1.list().get(0));
This always returns only the first element from the list.
Replace
System.out.println("sql1 " + query1.list());
By :
for(String id : query1.list() ) System.out.println("sql1 " + id);
I want to find table names & column names from a file named 'query' below.
var query = " SELECT accounts.name, SUM((COALESCE((jan_val_c),0)+ ";
query += " COALESCE((feb_val_c),0)+ COALESCE((march_val_c),0)+ COALESCE((apr_val_c),0)+ ";
query += " COALESCE((may_val_c),0)+ COALESCE((june_val_c),0)+ COALESCE((july_val_c),0)+ ";
query += " COALESCE((aug_val_c),0)+ COALESCE((sept_val_c),0)+ COALESCE((oct_val_c),0)+ ";
query += " COALESCE((nov_val_c),0)+ COALESCE((dec_val_c),0))) AS sales_plan,SUM((COALESCE((jan_actual_val_c),0)+ ";
query += " COALESCE( (feb_actual_val_c),0)+ COALESCE( (march_actual_val_c),0)+ COALESCE( (apr_actual_val_c),0)+ ";
query += " COALESCE( (may_actual_val_c),0)+ COALESCE( (june_actual_val_c),0)+ COALESCE( (july_actual_val_c),0)+ ";
query += " COALESCE( (aug_actual_val_c),0)+ COALESCE( (sept_actual_val_c),0)+ COALESCE( (oct_actual_val_c),0)+ ";
query += " COALESCE( (nov_actual_val_c),0)+ COALESCE( (dec_actual_val_c),0))) AS Actual_plan ,month_name_c, ";
query += " cl_sales_planning_month.year_c, cl_products.volume,cl_brands.name AS brand ,cl_therapies.name ";
query += " AS therapy,cl_products.name AS product, accounts.created_by,accounts.assigned_user_id , ";
query += " DATE_FORMAT(STR_TO_DATE(CONCAT_WS('-',cl_sales_planning_month.month_name_c, ";
query += " cl_sales_planning_month.year_c),'%M-%Y'),'%b-%y' ) AS monthyear FROM cl_sales_planning_month ";
query += " LEFT JOIN accounts ON cl_sales_planning_month.account_id_c =accounts.id LEFT JOIN cl_products ";
query += " ON cl_sales_planning_month.cl_products_id_c = cl_products.id LEFT JOIN cl_brands ON ";
query += " cl_products.cl_brands_id_c=cl_brands.id LEFT JOIN cl_therapies ON ";
query += " cl_products.cl_therapies_id_c=cl_therapies.id WHERE ";
query += " cl_sales_planning_month.month_name_c = MONTHNAME(CURRENT_DATE - INTERVAL 2 MONTH) AND ";
query += " cl_sales_planning_month.year_c = YEAR(CURRENT_DATE - INTERVAL 2 MONTH) AND";
query += " cl_sales_planning_month.user_id_c IN ("+ params["childs"].value +") ";
query += " GROUP BY therapy,monthyear ";
query += " ORDER BY STR_TO_DATE(cl_sales_planning_month.year_c,'%Y') ASC, ";
query += " STR_TO_DATE(cl_sales_planning_month.month_name_c,'%M') ASC, Actual_plan DESC ";
For this I have written a Java program:
package com.waprau;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.regex.Pattern;
public class SeparateTableNamesColumnNames {
public static void main(String[] args) {
File file = new File("/home/waprau/Desktop/query");
//Pattern = new Pattern("([^\\s]+(\\.(?i))$)");
try {
Scanner scanner = new Scanner(file);
scanner.useDelimiter("\\s|=|,|\\)|\\(|this.|\\].");
while(scanner.hasNext()){
if(scanner.next().matches("(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"))
System.out.println(scanner.next());;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
With above program I am able to separate all words. But I want to get only those words which contains a single dot or period e.g. accounts.name, cl_sales_planning_month.year_c, cl_products.volume, cl_brands.name, cl_therapies.name etc. However I am not able to find a pattern or whatever which can separate these words from file.
But it is not working.
This is the result I am getting:
And this is what I want:
Any help is appreciated.
To match words containing a dot, you can use: "\\w+\\.\\w+"?
\w matches letters, numbers, and underscores.
However, that would also match something which had more than one period. You could improve it by using look-arounds to make sure there is not another period before or after the word you are matching:
"(?<!\\.)\\b\\w+\\.\\w+\\b(?!\\.)"
This matches a word containing a dot, and cannot contain a dot immediately before or after. \b is a word boundary.
However, that would match decimal numbers like 123.45. Tables can contain numbers, but cannot start with one. So we could also ensure that each word starts with a letter:
"(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"
The period . has to be escaped as it means "any character". As this is not normal String escaping (like \n) it uses two backslashes: \\.
Also \\s.
Regardless of the regex (dan1111's answer appears to cover that). You have a flaw in your Java code, scanner.next() gets the next string, and since you call it twice so you won't print what you matched. Instead you will print the item following every match.
If you change your loop as follows it seems to print what you want:
String tmp;
while (scanner.hasNext()) {
// Store next item so we can match AND print it.
tmp = scanner.next();
if (tmp.matches("(?<!\\.)\\b[a-zA-Z]\\w*\\.[a-zA-Z]\\w*\\b(?!\\.)"))
System.out.println(tmp);
}