Query doesnt work on android, column '_id' does not exist? - android

I hope anyone can help me with this.
I'm using sqlite3 on my android app. I'm trying to do this query:
mCursor = conexion.getDatabase().rawQuery("SELECT employee.name, company.name FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
This is my schema:
CREATE table company ("_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT NOT NULL);";
CREATE table employee ("_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT NOT NULL, "
+ "fullName TEXT NOT NULL, "
+ "idCompany INTEGER NOT NULL, "
+ "FOREIGN KEY(idCompany) REFERENCES company (_id));";
When I run this query on my android app I get the following error:
05-09 22:35:23.170: E/AndroidRuntime(10920): FATAL EXCEPTION: main
05-09 22:35:23.170: E/AndroidRuntime(10920): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ej.ej/com.ej.ej.controlador.AplicacionActivity}: java.lang.IllegalArgumentException: column '_id' does not exist
If I run the same query but with select *:
mCursor = conexion.getDatabase().rawQuery("SELECT * FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idEmployee=company._id) ORDER BY employee.name", null);
No problem I get, it works fine. But since in my schema I have name for company and name for employee I need to differentiate both.
I tried doing this query using cmd and adb commands and it works. I really don't get why the error!!
EDITED: I made it work, as #HalR suggested in the query (dont know why) I have to retrieve the ids. So now I have:
mCursor = conexion.getDatabase().rawQuery("SELECT company._id, employee.name as employee, company.name as company FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
But I had one more issue and it wasnt in the query, it was on my ActivityFragment (thanks to #Hoan Nguyen, he made me see this part of the code again):
Listing my employees, I was getting the name of my employee and the idCompany. Don't know why, but this was looking for the _id of Company instead of idCompany of Employee.
String[] from = new String[] { "name", "idCompany"};
int[] to = new int[] { R.id.textViewNombreIzq, R.id.textViewNombreCent };
ListView lvEmployee = (ListView) view.findViewById (android.R.id.list);
ListClientsCursorAdapter notes = new ListClientsCursorAdapter(context, R.layout.activity_file_client, mCursorEmployee, from, to, 0);
lvEmployee .setAdapter(notes);
I just changed:
String[] from = new String[] { "name", "idCompany"};
For:
String[] from = new String[] { "employee", "company"};
And now is fine. Thanks to all, for your help I really apreciated :).

first, I in your CREATE TABLE employee statement you used the lable full name as a column label. If it is not a typo here, please change it to something like full_name. you can't just use spaces in column labels this way.
second, use this query string:
SELECT employee.name, company.name FROM employee INNER JOIN company ON (employee.idCompany=company._id) ORDER BY employee.name. Notice the ON expression. it's employee.idCompany not employee.idEmployee.
fix those first, and let me know if the error still exists.

I think you want this:
mCursor = conexion.getDatabase().rawQuery("SELECT employee.idCompany, employee.name, company.name FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
Note: You need to make sure you specify the column name you are comparing in the section just after the SELECT.

Actually you don't need to name your column as _id in your table. for a example, you can create column as company_id in your company table and when you write your query, you can specify this column as below.
select company_id as _id, name from company.

Related

How to write SQL statement containing 2 conditions in android

I am trying to delete a row from my table if 2 columns equal to what the user entered.
E.g. I have 2 textfields in which the user entered something in both e.g. "chicken" and in the other textfield "car". I want to delete the row in which those 2 values are in a row. I think it will be something like: delete from ~tablename~ where food = chicken AND vehicle = car.
Im not sure how to write that in sqlite in android.
I have my SQLitedatabase object and have called the delete method on it, but not sure what to put in the parameters
EDIT = I've managed to do it. Thanks for the below answers but this is how I've done it:
sqlitedb.delete("Random", "food =? AND vehicle=? ", new String[]{tv.getText.toString(),tv1.getText.toString()});
tv and tv1 are textfields in my case. Random is my table's name.
The sql query will look like -
String sqlQuery = "DELETE FROM <table_name> WHERE food = '"+ <food_name> + "' AND vehicle = '" + <vehicle_name> + "'";
You want something like:
String table_name=~tablename~;
String table_column_one=food;
String table_column_two=vehicle;
database.delete(table_name,
table_column_one + " = ? AND " + table_column_two + " = ?",
new String[] {"chicken", "car"});
Check SQLiteDatabase's documentation on delete function for more info.
SQLite accepts conditionals in the WHERE clause as regular SQL.

android second column returns no value

I have a problem to create a table. If I try to get a value from the second column, android writes a empty space in the toast. But if I try to get a value from the first column, android writes the value of the column correctly. The query functions to write the first column and to write the second column are equal. So I think the Creation of the Table is the problem. But look yourself:
public SQLiteDatabase tabelleerstellen(){
SQLiteDatabase leveldatabase = openOrCreateDatabase("leveldata.db",SQLiteDatabase.CREATE_IF_NECESSARY, null);
leveldatabase.setVersion(1);
final String CREATE_TABLE_LEVEL =
"CREATE TABLE IF NOT EXISTS tbl_level ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "ME1 TEXT, "
+ "ME2 TEXT, "
+ "ME3 TEXT, "
+ "ME4 TEXT, "
+ "ME5 TEXT, "
+ "ME6 TEXT, "
+ "ME8 TEXT, "
+ "GESCHAFFT INTEGER);";
leveldatabase.execSQL(CREATE_TABLE_LEVEL);
return leveldatabase;
}
public void tester(SQLiteDatabase leveldata){
ContentValues cursortester = new ContentValues();
cursortester.put("ME2","25");
leveldata.insert("tbl_level",null,cursortester);
String[] testerpr = {"ME2"};
Cursor testerprüfen = leveldata.query("tbl_level",testerpr,null,null, null, null,null,null);
testerprüfen.moveToFirst();
String dada = testerprüfen.getString(testerprüfen.getColumnIndex("ME2"));
Toast testertoast = Toast.makeText(getApplicationContext(),dada,Toast.LENGTH_SHORT);
testertoast.show();
}
Please check the following things:
Please make sure the table is up to date .. so try to call DROP TABLE IF EXISTS tbl_level; and recreate the table.
If you run a test make sure the table is completely empty ... so delete everything at the beggining of the test.
If the table can contain elements during the test then make sure you check the last inserted element. Please note that calling testerprüfen.moveToFirst(); moves the cursor to the first row in the table so checking that row every time is even if the table contains 50 elements is not a good thing. In this case you either use a sorting option in your query of uese while (testerprüfen != null && testerprüfen.moveToNext()) {// Your code here}
All in all I think your problem is that you already inserted more that one element in the able but you always check only the first element (with testerprüfen.moveToFirst();). Please not that there is a cursor.moveToLast() method that you can also call. This method moves the cursor to the last row in the table.

Delete the last row in a table SQLite android

I am developing an android app where I want to delete the last row in one of my database table. I have tried the code below, but its throwing a syntax error.
public void deletelatestprofilefromsystemsettings()
{
String maxid = System_id + "="+"SELECT MAX ("+System_id+") FROM" +TABLE_SYSTEM_SETTINGS;
getWritableDatabase().delete(TABLE_SYSTEM_SETTINGS, maxid ,null);
}
Please help! Thanks!
You are lacking a space after the FROM, and subqueries must be written in parentheses:
String maxid = System_id + "=" +
"(SELECT MAX("+System_id+") FROM " + TABLE_SYSTEM_SETTINGS + ")";
You are trying to execute a DELETE with a SELECT in the same query. AFAIK you shouldn't do it. You have to execute the SELECT query first, in order to retrieve the desired id, then execute the deletion. In other words, execute Cursor c = getWritableDatabase().query(), read the id from the cursor, then use it in getWritableDatabase().delete().
Also, add a space after ") FROM", so it becomes ") FROM " in order to avoid a syntax error.

Android - Database SQLite - convert boolean values

I am working on an Android project with a SQLite database and have a column in the database consisting of a boolean value (which store 1s and 0s) of whether an individual in the database is important.
What I am trying to do is output into a textview listview a "!" if an individual is important, and " " if they are not important using a cursor and cursor adaptor. I can get the "1" and "0"s to appear in the listview, but my question is how/where do I convert these to "!" and " "?
The query I am currently using is
return database.query("people", new String[] {"_id", "important"}, null, null, null, null, "important" + " DESC, " + "name" + " ASC");
The easiest way is to do this in the database query.
The query function is too inflexible for that, so you have to use rawQuery instead:
db.rawQuery("SELECT _id, " +
"CASE WHEN important THEN '!' ELSE ' ' END AS important " +
"FROM people " +
"ORDER BY important DESC, name ASC", null);
If it is a custom ListView which I am pretty sure it is, then you'll have to do that in your CustomAdapter for the ListView, which takes care of populating the ListView with the data you pass to it.Check this out.
Doing it is pretty simple, just loop through your Cursor and do if else statement.

How do I join two SQLite tables in my Android application?

Background
I have an Android project that has a database with two tables: tbl_question and tbl_alternative.
To populate the views with questions and alternatives I am using cursors. There are no problems in getting the data I need until I try to join the two tables.
Tbl_question
-------------
_id
question
categoryid
Tbl_alternative
---------------
_id
questionid
categoryid
alternative
I want something like the following:
SELECT tbl_question.question, tbl_alternative.alternative where
categoryid=tbl_alternative.categoryid AND tbl_question._id =
tbl_alternative.questionid.`
This is my attempt:
public Cursor getAlternative(long categoryid) {
String[] columns = new String[] { KEY_Q_ID, KEY_IMAGE, KEY_QUESTION, KEY_ALT, KEY_QID};
String whereClause = KEY_CATEGORYID + "=" + categoryid +" AND "+ KEY_Q_ID +"="+ KEY_QID;
Cursor cursor = mDb.query(true, DBTABLE_QUESTION + " INNER JOIN "+ DBTABLE_ALTERNATIVE, columns, whereClause, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
I find this way to form queries harder than regular SQL, but have gotten the advice to use this way since it is less error prone.
Question
How do I join two SQLite tables in my application?
You need rawQuery method.
Example:
private final String MY_QUERY = "SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.other_id WHERE b.property_id=?";
db.rawQuery(MY_QUERY, new String[]{String.valueOf(propertyId)});
Use ? bindings instead of putting values into raw sql query.
An alternate way is to construct a view which is then queried just like a table.
In many database managers using a view can result in better performance.
CREATE VIEW xyz SELECT q.question, a.alternative
FROM tbl_question AS q, tbl_alternative AS a
WHERE q.categoryid = a.categoryid
AND q._id = a.questionid;
This is from memory so there may be some syntactic issues.
http://www.sqlite.org/lang_createview.html
I mention this approach because then you can use SQLiteQueryBuilder with the view as you implied that it was preferred.
In addition to #pawelzieba's answer, which definitely is correct, to join two tables, while you can use an INNER JOIN like this
SELECT * FROM expense INNER JOIN refuel
ON exp_id = expense_id
WHERE refuel_id = 1
via raw query like this -
String rawQuery = "SELECT * FROM " + RefuelTable.TABLE_NAME + " INNER JOIN " + ExpenseTable.TABLE_NAME
+ " ON " + RefuelTable.EXP_ID + " = " + ExpenseTable.ID
+ " WHERE " + RefuelTable.ID + " = " + id;
Cursor c = db.rawQuery(
rawQuery,
null
);
because of SQLite's backward compatible support of the primitive way of querying, we turn that command into this -
SELECT *
FROM expense, refuel
WHERE exp_id = expense_id AND refuel_id = 1
and hence be able to take advanatage of the SQLiteDatabase.query() helper method
Cursor c = db.query(
RefuelTable.TABLE_NAME + " , " + ExpenseTable.TABLE_NAME,
Utils.concat(RefuelTable.PROJECTION, ExpenseTable.PROJECTION),
RefuelTable.EXP_ID + " = " + ExpenseTable.ID + " AND " + RefuelTable.ID + " = " + id,
null,
null,
null,
null
);
For a detailed blog post check this
http://blog.championswimmer.in/2015/12/doing-a-table-join-in-android-without-using-rawquery
"Ambiguous column" usually means that the same column name appears in at least two tables; the database engine can't tell which one you want. Use full table names or table aliases to remove the ambiguity.
Here's an example I happened to have in my editor. It's from someone else's problem, but should make sense anyway.
select P.*
from product_has_image P
inner join highest_priority_images H
on (H.id_product = P.id_product and H.priority = p.priority)

Categories

Resources