Use variable for column name in sql query - java

I'm searching for a word (variable) that occurs in multiple columns of a table. The search has to return the name of the columns in which the word in found.
I could use a foreach loop to go through each column seperately and know the presence of the word in that particular column when the returned cursor isn't null.
The problem is on how to use two different variables (one for column name and one for the word) in SQL query or rawQuery.
My code is as follows:
String[] columnsList = {"col1","col2","col3"};
String[] wordsList = {"fireman","camper","builder"};
for(String i : wordsList){
for(String j : columnsList){
Cursor wordQuery = myDatabaseHandle.rawQuery("Select * from myTableOne WHERE " + j + " = ?",new String[]{i});
if(!(wordQuery==null)){
Toast.makeText(this,j+"is success",Toast.LENGTH_SHORT).show();
}
}
}
But i'm unable to get the answer. I used a seperate string as:
String queryString = "Select * from myTableOne WHERE " + j ;
and in the query,
Cursor WordQuery = myDatabaseHandle.rawQuery(queryString+" = ?",new String[]{i});
But, it's just toasting the names of all columns.

Your error is here:
if(!(wordQuery==null)){
The cursor is never null.
It can contain 0 records, though.
You can check its length by using wordQuery.getCount()
Something like:
if((wordQuery.getCount() > 0)){

Related

Android SQLite rawQuery - How to select multiple rows of a table

I'm trying to use rawQuery to return a cursor with a few different rows of data to be passed into it. When there is only 1 argument it works. When there is more than 1 argument it displays the empty ListView state. I believe the issue lies here:
// Query for items from the database and get a cursor back. Edited code for clarity:
recipeCursor = db.rawQuery("SELECT course, name, _id " +
" FROM recipes WHERE _id = ?",
selectedRecipesSQL);
When the code works the selectedRecipesSQL would look something like:
String[] selectedRecipesSQL;
selectedRecipesSQL = new String[]{"2"};
And when it doesn't work it would be something like
String[] selectedRecipesSQL;
selectedRecipesSQL = new String[]{"2 OR 5"};
So, to be clear, I can display a single row of the table in my ListView, but if I try to display more than one row of the table then it won't display anything.
One ugly solution which has crossed my mind (but I haven't pursued) is that I need to edit the rawQuery selection statement to read something like:
recipeCursor = db.rawQuery("SELECT course, name, _id " +
" FROM recipes WHERE _id = ? OR _id = ? OR _id = ?",
selectedRecipesSQL);
I'd probably use a for loop to generate the correct amount of WHERE "_id = ?" and then use a string array:
selectedRecipesSQL = new String[]{"2", "5"};
One way of doing it is by passing the possible values of _id as 1 string which is a comma separated list like this:
selectedRecipesSQL = new String[]{"1,2,3"};
and in your query use the operator LIKE:
recipeCursor = db.rawQuery(
"SELECT course, name, _id FROM recipes WHERE ',' || ? || ',' LIKE '%,' || _id || ',%'",
selectedRecipesSQL
);
This works also for just 1 value.
static String multiply__concat_string(String text,String joiner_,int multiple_)
{
String output="";
for(int i=0;i<multiple_;i++)
{
output+=(text+joiner_);
}
if(output.length()>0)
{
output=output.substring(0,output.length()-1);
}
return output;
}
Use it like this :
selectedRecipesSQL = new String[]{"2", "5"};
db.rawQuery("SELECT course, name, _id " +
" FROM recipes WHERE _id IN("+multiply_concat_string("?",",",selectedRecipesSQL.length)+")",
selectedRecipesSQL);

How can I account for the " ' " symbol (assigned to a name in a variable) as it causes my SQLite query to fail

In the app I am building, I need to access an SQLite database run a query in which I have a name in the "where" clause. This name is randomly generated (from another query) and is assigned to a global variable. This variable then get's passed to another query (in another method) where it's used. Something a little like this:
public class DatabaseAccess {
public static String player_name;
Cursor c = null;
public String getPlayerName(String string) {
c = db.rawQuery("select player_name FROM name_table where level = 1 ORDER BY RANDOM() LIMIT 1", new String[]{});
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String diff = c.getString(0);
buffer.append("" + diff);
}
player_name = buffer.toString();
return buffer.toString();
}
public String getClue(String string) {
c = db.rawQuery("SELECT clue FROM clue_table where player_name = '" + player_name +"'", new String[]{});
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String diff = c.getString(0);
buffer.append("" + diff);
}
return buffer.toString();
}
The issue is that some of the names in the database have a ' symbol in them (for example Dara O'Briain).
When a name like this comes up, my code crashes with the error message:
Caused by: android.database.sqlite.SQLiteException: near "Briain": syntax error (code 1): , while compiling: select alt_name FROM player_names where player_name = 'Dara O'Briain'
It looks like it see's the ' as a means to end the string and this causes a faulty query.
How can I account for these instances in my code?
c = db.rawQuery("SELECT clue FROM clue_table where player_name = '" +
player_name +"'", new String[]{});
// see here ^^^^^^^^^^^^^^
Ok, so that empty String[] array you're passing to the call is exactly the place parameters are supposed to go. So, the query should look like that:
c = db.rawQuery("SELECT clue FROM clue_table where player_name = ?", new String[]{player_name});
Just put a question mark where you want the parameter inserted. They will be inserted in order, the array can have more of these.
The driver will take care of escaping any apostrophes for you. If you don't escape user input in any way, you risk a lot. Consider player name coming from user input in the app, and they write into the search box on a whim:
' delete from users; --
If you just paste it into your query it now looks like this:
SELECT clue FROM clue_table where player_name = ''; delete from users; --'
And you get your data dropped as a free bonus to search function.

How to get number of particular name in sqlite table by query

I have a table in which name and number of people are stored. Now I want to make a method in sqlite helper class which will return the number of particular person whose name I will pass in the method
There is something wrong with my code.
Here is my code
public String fetchGroup(SQLiteDatabase inDatabase, String valueCheck){
String query = "SELECT * FROM groups WHERE groupname='" + valueCheck;
Cursor cursor = inDatabase.rawQuery(query,null);
String place = cursor.getString(cursor.getColumnIndex("contactid"));
return place;
Take care to use cursor.moveToFirst() command before reading datas
Else, instead counting the number of people in Java, you can just modify your query to have only this number return.
Something like this :
public String fetchGroup(SQLiteDatabase inDatabase, String valueCheck){
String query = "SELECT COUNT(id) FROM groups WHERE groupname=\"" + valueCheck + "\"";
Cursor cursor = inDatabase.rawQuery(query, null);
cursor.moveToFirst();
int place = cursor.getInt(0);
return String.valueOf(place);
}
After your query do
int count = 0;
while (cursor.moveToNext()) {
// increment variable
count++;
}
after iterating you will get number of count

sql query to check existing records

I have data in following format:
HashMap<PageID, Set<SubscriberIDS>>
What I need to check is how many SubscriberIDS for each of the PageIDs do not exist in a MySQL table already. MySQL table has PageID and SubscriberID columns.
This is what I have so far:
String NEW_SUBSCRIBER_COUNT = "SELECT ? - COUNT(*) as new_subscribers from FB_SUBSCRIPTIONS WHERE PAGEID=? AND SUBSCRIBERID IN (?)";
First parameter being numberOFSubscriberIDs, Second being PageId and Third being SubscriberIds
but this will need to be hit for each pageId. How do I modify it to give me number of new subscribers for each PageID using single query.
Is there any specific need to do it in one query? Because while it can, it might actually be more readable to use your original solution and invoke a query for each page id. In any case, what you want can't be done in a single line, so you need to expect to loop at a given point.
// Build dynamic query
StringBuilder whereClause = new StringBuilder();
Iterator<PageID> it = yourMap.keySet().iterator();
while(it.hasNext()){
PageID key = it.next();
Set<SubscriberIDS> value = yourMap.get(key);
// You need to fill the 'IN' clause with multiple parameters, one for each subscriber id
StringBuilder inClause = new StringBuilder();
for(SubscriberIDS subId : value){
if(inClause.length > 0){
inClause.append(", ");
}
inClause.append("?");
preparedStatement.setInt(paramIndex++, subId.getId());
}
// For each page id we append a new 'OR' to our query
if(whereClause.lenght > 0){
whereClause.append(" OR ");
}
whereClause.append("(PAGEID=? AND SUBSCRIBERID IN (").append(inClause.toString()).append("))");
}
String query = "SELECT PAGEID, COUNT(SUBSCRIBERID) AS SUBSCRIBERS FROM FB_SUBSCRIPTIONS WHERE " + whereClause.toString() + " GROUP BY PAGEID";
// Create prepared statement and set parameters
PreparedStatement preparedStatement = connection.prepareStatement(query);
int paramIndex = 0;
it = yourMap.keySet().iterator();
while(it.hasNext()){
PageID key = it.next();
Set<SubscriberIDS> value = yourMap.get(key);
preparedStatement.setInt(paramIndex++, key.getId());
for(SubscriberIDS subId : value){
preparedStatement.setInt(paramIndex++, subId.getId());
}
}
// Execute query, loop over result and calculate new subscriptions
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
int pageId = rs.getInt("PAGEID");
int newSubscriptions = yourMap.get(pageId).size() - rs.getInt("SUBSCRIBERS");
System.out.println(pageId + ", " + newSubscriptions);
}
Given following data in your map:
PAGEID SUBSCRIBERIDS
1 1,3,4,5,9
2 3,4,5,6,8,9
3 2,5,6
And following data in the DB:
PAGEID SUBSCRIBERIDS
1 3,4,10,11
2 1,2,5,7
3 1,2,5,6,7,8,9
This should give following output:
1,3
2,6
3,0
I haven't actually ran the code, so it might need some adjustments, but it gives you the general idea...

keep column name variable in Java INSERT INTO command with PreparedStatement?

I have the following problem:
I have two tables in one data base which consist of the same columns besides the name of the last column. I want to write data into them using Java.
I want to use the same preparedStatement for both tables, where I check with an if-command whether it is table1 or table2. table2 has amount10 as the name for the last column, table1 has amount20 for it. This number is stored in a variable within my code.
Below you can see a (simplified) example and how I tried to let the column name variable but it doesn't work. Is there any way to fix this without copying the whole statement and manually changing the number variable?
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount`+"number") VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount`+"number" = ? ; ";
PreparedStatement insertDataStmt;
This will not work since variables number and table are not going to be magically injected into your insertData string while you are changing them.
I'd to a method prepareInsertstatement(String table, String number) that would return correct PreparedStatement:
public void prepareInsertStatement(Connection conn, Strint table, String number) {
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount+"number"') VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount+"number"' = ? ; ";
PreparedStatement insertDataStmt = conn.prepareStatement(insertData);
return insertDataStmt;
}
Just remember to close the PreparesStatement when you don't need it any more.
I suppose that reason for that is invalid syntax. When you concatenate string for last column name you use code 'amount' + number. If your number value is 20, than concat result will be
'amount'20 that cause invalid syntax exception. Just move one extra ' after number.
"'amount" + number + "'"
Note: log, or just error that appears during this statement execution would be very useful to find right answer for your question.

Categories

Resources