Query is not returning any data SQLite - java

I have database with 4 columns int id | String data | String date | int boot and i have some data in it. I have method getRow(String s) when i call it with string for id or data and change query to that option it works but when i´m trying to get row with equal date it won´t pass cursor.moveToFirst condition.
Here is my code:
String CREATE_TABLE = "CREATE TABLE "
+ TABLE_NAME + "(" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_DATA
+ " TEXT," + COLUMN_DATE + " TEXT," + COLUMN_BOOT + " Integer" + ")";
public String getRowID(String id){
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + TABLE_NAME + " where " + COLUMN_ID + " = " + id, null);
if (c != null && c.moveToFirst()) {
//loggin succes
return "string";
}else return null;
}
public String getRowDate(String date){
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = " + date, null);
if (c != null && c.moveToFirst()) {
//loggin succes
return "string";
}else return null;
}
myDb.getRowID("1"); returning something
myDb.getRowDate("02122016"); returning null
I have two rows in my database.
1 | 0.19 | 01122016 | 0
2 | 0.19 | 02122016 | 0

Be wary when comparing integers and strings. You may wonder why SQLite would be comparing integers at all since your arguments are strings, until you consider that your raw query looks like this:
select * from TABLE where DATE = 02122016
That value is interpreted as an integer and converted to text, but it loses the leading zero in the process. You can verify this with a sqlite3 shell:
sqlite> select 02122016;
2122016
sqlite> select '02122016' = 02122016;
0 -- false
sqlite> select cast(02122016 as text);
2122016
The simplest fix is to quote the value using a method from DatabaseUtils:
String escaped = DatabaseUtils.sqlEscapeString(date);
String query = "select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = " + escaped;
A better fix would be to use a placeholder argument instead. Note that Android binds all arguments as strings:
String query = "select * from " + TABLE_NAME + " where " + COLUMN_DATE + " = ?";
db.rawQuery(query, new String[]{date});
However, my advice would be to not use rawQuery() and instead use one of the real query() methods. Here's a good example.
Lastly, perhaps you should consider a different format for storing dates. In practice I usually either store an INTEGER column with a unix timestamp (seconds or milliseconds since epoch), or I use a TEXT column with values in the yyyy-MM-dd format since this is implicitly supported by numerous datetime functions in SQLite.

Related

Error no such column in SQLite when updating rows

I'm trying to update data in rows in my DB, but i catch error that there's no such column (no such column 'Moscow' or another)
This is DBHelper code:
public static final String tableName = "currentWeather";
public static final String KEY_ID = "_id";
public static final String cityName = "city";
public static final String cityTemp = "temperature";
And creating DB:
sqLiteDatabase.execSQL("create table " + tableName + "(" + KEY_ID + "
integer primary key autoincrement,"
+ cityName + " text," + cityTemp + " text, " + " UNIQUE(" + cityName +
"))");
and error shows when i try to execSQl in response:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " +
DBHelper.cityTemp + "=" +
response.body().getForecastMain().getTemp() + "
WHERE "
+ DBHelper.cityName + "=" + cityName);
I expect to update temperature data in rows by cityName
cityName and response.body().getForecastMain().getTemp() are strings and they should be passed surrounded with single quotes to the sql statement:
sqLiteDatabase.execSQL(
"UPDATE " + DBHelper.tableName + " SET " + DBHelper.cityTemp + "='" + response.body().getForecastMain().getTemp() + "'" +
"WHERE " + DBHelper.cityName + " = '" + cityName + "'"
);
But the recommended and safe way of doing the update is with the use of ContentValues and ? as placeholders for the parameters:
ContentValues cv = new ContentValues();
cv.put(DBHelper.cityTemp, String.valueOf(response.body().getForecastMain().getTemp()));
int rows = sqLiteDatabase.update(
DBHelper.tableName,
cv,
DBHelper.cityName + " = ?",
new String[] {cityName}
);
You can examine the value of the integer variable rows.
If it is 1 this means that 1 row was updated (because cityName is unique) so the update was successful.
I think you have changed column name or add new one (city). So you can fix it by two ways
By uninstall the application from phone
Add column name in upgrade method.
Example:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}
The thing is you need to wrap the values after the = sign in single quotations in the UPDATE statement. As for digits they work in both cases.
For example here is the correct syntax
UPDATE currentWeather
SET temperature = 45
WHERE
city = 'Moscow'
But in your code I'm assuming cityName has the value Moscow without the single quotation marks so the converted SQL code will be like this
UPDATE currentWeather
SET temperature = 45
WHERE
city = Moscow
Now the sql interpreter will think Moscow is some database object or column or something and not a literal value. So you need to surround your values in single quotation marks.
Also consider What the data type of response.body().getForecastMain().getTemp() is.
If it's int you have to parse it or something, as the data type of the related column is Text.

Issue deleting row from SQL Table

I'm trying to remove a row from an SQL table using this code below. However, whenever I call this method I get this following error:
android.database.sqlite.SQLiteException: no such column: Plumber (code 1): , while compiling: DELETE FROM service WHERE name = Plumber
public boolean deleteService(String name){
SQLiteDatabase db = this.getWritableDatabase();
boolean result = false;
String query = "SELECT * FROM "
+ TABLE_SERVICE
+ " WHERE "
+ COLUMN_NAME
+ " = \""
+ name
+ "\""
;
Cursor cursor = db.rawQuery(query, null);
if(cursor.moveToFirst()){
String nameStr = cursor.getString(0);
db.delete(TABLE_SERVICE, COLUMN_NAME + " = " + nameStr, null);
cursor.close();
result = true;
}
db.close();
return result;
}
This is my table
public void onCreate(SQLiteDatabase db){
String CREATE_USERS_TABLE = "CREATE TABLE " +
TABLE_SERVICE + "("
+
COLUMN_NAME + " TEXT," +
COLUMN_RATE + " TEXT," +
COLUMN_CATEGORY + " TEXT," + COLUMN_SUBCATEGORY + " TEXT)";
db.execSQL(CREATE_USERS_TABLE);
}
First you're fetching all the rows that in COLUMN_NAME have the value name.
Next you want to delete the 1st of these rows (maybe it's the only one?) because nameStr gets the value of the 1st column which is COLUMN_NAME.
Why are you doing this?
Just execute this statement:
int number = db.delete(TABLE_SERVICE, COLUMN_NAME + " = '" + name + "'", null);
if number gets the value 0 then no rows were deleted, else it gets the number of deleted rows.
delete deletes rows not columns.
If you want to get rid of a column, you need to drop it. The SQL syntax is:
alter table table_service drop column <column_name>;
I don't know how to express this in java with the methods that you are using.
Ensure that your SQL syntax is correct, and that "Plumber" is a string with double quotes. By my experience, these errors are usually caused by an incorrect column or name.
Use this format:
DELETE FROM table_name WHERE condition(s)
SQLite browser can also help you visualize your database.

Android - SQlite insert not inserting

So i am trying to insert some data in the internal sqlite database but after i run the insert no data has been added. There are, as far as i can see no errors in the logs and every debug log i put into it is shown. If i try to run the query that is returned in the log in sqlitestudio it works without a problem so i haven't got a clue as to what is going wrong.
#Override
public void onCreate(SQLiteDatabase db) {
String SQL = pictureTable();
db.execSQL(SQL);
}
private String pictureTable() {
return "CREATE TABLE geophoto_db_pictures ( picid integer,"
+ "name varying character(50),"
+ "city varying character(20) NOT NULL,"
+ "zipcode varying character(20) NOT NULL,"
+ "country varying character(20) NOT NULL,"
+ "picdate datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,"
+ "tags varying character(200),"
+ "image varying character(200) NOT NULL,"
+ "uploaded integer NOT NULL DEFAULT 0, PRIMARY KEY (picid))";
}
#Override
public void savePicture(Picture pic) {
Log.d(LOG_TAG, "saving picture started. Data: " + pic.getName());
// clean the inputs
String name = pic.getName();
String city = pic.getCity();
if (city != null) {
city = "'" + city + "'";
}
String country = pic.getCountry();
if (country != null) {
country = "'" + country + "'";
}
String zip = pic.getZipcode();
if (zip != null) {
zip = "'" + zip + "'";
}
String tags = tagsToString(pic.getTags());
String image = pic.getImage();
// Insert Query, all possible null values on "not null" rows will be
// replaced by a default value.
String SQL = "INSERT INTO geophoto_db_pictures(name, city, zipcode, country, tags, image)"
+ "VALUES('"
+ name
+ "',"
+ "IFNULL("
+ city
+ ", 'Unknown')"
+ ","
+ "IFNULL("
+ zip
+ ", 'Unknown')"
+ ","
+ "IFNULL("
+ country + ",'Unknown')" + ",'" + tags + "','" + image + "')";
Log.d(LOG_TAG, SQL);
executeWriteQuery(SQL);
ArrayList<Picture> list = getAllPictures();
Log.d(LOG_TAG, "Size :"+list.size());
}
private Cursor executeWriteQuery(String query){
Log.d(LOG_TAG, "execute write query");
SQLiteDatabase db = getWritableDatabase();
Cursor response = db.rawQuery(query, null);
Log.d(LOG_TAG, "write query executed");
return response;
}
All tips/help greatly appreciated!
Thomas
Try to put a semicolon at the end of table creation query. In your case as show below
private String pictureTable() {
return "CREATE TABLE geophoto_db_pictures ( picid integer,"
+ "name varying character(50),"
+ "city varying character(20) NOT NULL,"
+ "zipcode varying character(20) NOT NULL,"
+ "country varying character(20) NOT NULL,"
+ "picdate datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,"
+ "tags varying character(200),"
+ "image varying character(200) NOT NULL,"
+ "uploaded integer NOT NULL DEFAULT 0, PRIMARY KEY (picid));";
}
While providing a query through an external String, you will need to provide SQL query with an end of statement ;. Using the primitive SQLite does not require ; as it just takes arguments and create function query itself. I have experienced both cases and I ended up understanding the way I have put it here.
The problem you are facing is that you are trying to use rawQuery() to insert a record, when you should be using execSQL() instead (see this answer).
So, the correct code for executeWriteQuery would be as follows:
private void executeWrite(String command){
Log.d(LOG_TAG, "execute write");
SQLiteDatabase db = getWritableDatabase();
db.execSQL(command);
Log.d(LOG_TAG, "write executed");
}
Also, consider using insert() instead as that will allow you to get a return value to determine whether or not the data was inserted successfully.

Android SQLite rawQuery with WHERE clause returns search string as column not found

I have created a table called CHEMISTID:
private static final String CREATE_TABLE_CHEMISTID = "CREATE TABLE "
+ CHEMISTID + "(" + KEY_ID + " INTEGER PRIMARY KEY, " + KEY_CHEMISTID
+ " TEXT" + ")";
My insert function works properly but when I run a search query to find if a chemistId is already present using the following query statement:
String selectQuery = "SELECT * FROM " + CHEMISTID +" WHERE " + KEY_CHEMISTID + " = "+ chemistID + ";";
Cursor c = db.rawQuery(selectQuery,null);
My logcat displays the following error message:
E/AndroidRuntime(1169): FATAL EXCEPTION: main
E/AndroidRuntime(1169): android.database.sqlite.SQLiteException: no such column: Spain (code 1): , while compiling: SELECT * FROM chemistIdTable WHERE chemistId = Spain;
Where Spain is a particular chemistId that I have dynamically created in my program.
How should I fix my selectQuery String so that it searches in the column name KEY_CHEMISTID for a particular String chemistId?
You need to quote your strings such as Spain in SQL so they get taken as string literals and not column name identifiers. You can use single quotes like 'Spain' for that.
However it's much better to use ? parameter placeholders instead and supply the parameter values in the selection args array, like:
... KEY_CHEMISTID + "=?" ...
c = db.rawQuery(selectQuery, new String[] { chemistID });
You missed single quote,So change
String selectQuery = "SELECT * FROM " + CHEMISTID +" WHERE " + KEY_CHEMISTID + " = "+ chemistID + ";";
to
String selectQuery = "SELECT * FROM " + CHEMISTID +" WHERE " + KEY_CHEMISTID + " = '"+ chemistID + "';";
Recommended solution is to use parameterized query as
Cursor c = db.query(CHEMISTID, null, KEY_CHEMISTID + "=?",
new String[] { chemistID },null, null, null, null);

Retrieve Data from Sqllite DB between Two dates android

I retrieve data between two dates some how it get correct result and some how it output empty listview when i select dates with month it work properly but when i select dates between more than one month it output empty listview below is my codes
here i declare the variable in DB class
public static final String EX_RowID = "_id";
public static final String EX_Cattype = "Ecattype";
public static final String EX_Date = "Ecdate";
public static final String EX_Price = "Ecprice";
public static final String EX_Type = "itype";
creat table statement
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + Food_TABLE +"(" +
EX_RowID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
EX_Cattype + " TEXT NOT NULL, " +
EX_Date + " TEXT NOT NULL," +
EX_Price + " INTEGER NOT NULL," +
EX_Type + " TEXT NOT NULL UNIQUE );"
);
}
enter data Method
public long ExEntry(String Ecatgtype, String Edate, String Eprice, String Eitype) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues();
cv.put(EX_Cattype, Ecatgtype);
cv.put(EX_Date, Edate );
cv.put(EX_Price, Eprice);
cv.put(EX_Type, Eitype);
return ourdatabase.insertOrThrow(Food_TABLE, null, cv);
}
here i access the ExEntry Method
ExMgDB Expentry = new ExMgDB(ADD_EX.this);
Expentry.open();
Expentry.ExEntry(cate, date, price, itype);
Expentry.close();
here i am facing the problem between these two dates variables
public Cursor CstmRpot(String fd, String td) {
// TODO Auto-generated method stub
String[] columns = new String[] {EX_RowID,EX_Cattype, EX_Date, EX_Price, EX_Type };
Cursor c= ourdatabase.query(Food_TABLE, columns, EX_Date + " BETWEEN '" + fd + "'
AND '" + td + "'" , null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
i access it like below
CustemRpt dbcs = new CustemRpt();
Cursor cursor = CstDB.CstmRpot(frmdate,tondate);
There are two major solutions. All solutions have in common, that the column containing the date has to be ordered somehow. If this order is destroyed your data is corrupt and your queries cannot return the expected results!
1. Save your Dates as INTEGER in your database and use a method to map Dates to a number:
A possible way is to use Date.getTime () to map Dates to numbers, but there are many others. Important is that
equal dates get the same number and
that a date that is after another date gets a bigger number.
This way ordering will be correct for sure.
To achieve this with `Java.util.Date.getTime() you only have to set the time to 0:00:00:000 if you want to store date only.
For example:
"CREATE TABLE " + Food_TABLE +"(" +
EX_RowID + "INTEGER PRIMARY KEY AUTOINCREMENT, " +
EX_Cattype + " TEXT NOT NULL, " +
EX_Date + " INTEGER NOT NULL," +
EX_Price + " INTEGER NOT NULL," +
EX_Type + " TEXT NOT NULL UNIQUE );"
private static String dateOnly(java.util.Date d) {
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return Long.toString(cal.getTimeInMillis());
}
public Cursor CstmRpot(java.util.Date fd, java.util.Date td) {
// TODO Auto-generated method stub
String[] columns = new String[]{EX_RowID,EX_Cattype, EX_Date, EX_Price, EX_Type };
Cursor c= ourdatabase.query(Food_TABLE, columns, EX_Date + " > " + dateOnly (fd) + " AND " + EX_Date + " < " + dateOnly(td), null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
If you don't use different timezones the dateOnly(java.util.Date d) can be optimized.
Of course you can also use JODA-time.
2. Save your Dates as TEXT
If you choose this method your queries that are comparing the date-column are going to be a bit slower, but the entries in the database are human readable which doesn't have t be the case with method 1.
TEXT-columns are ordered with BINARY by default, which means memcmp() is used to compare the values and to determine which value is greater or if the values are equal. (Remember x BETWEEN a AND b means x <= a AND x >= b.)
You can examine the work of memcmp() with this function memcmp().
To ensure you get the right results you have to ensure the following:
All date-values in your database have to have the same text length.
All date-values in your database have to be in the same Format. The bigger date-parts (year) have to be before the smaller date-parts (month).
All Parameters for date-values in queries have to follow these rules too.
A possible date-format may look like this: yyyy-MM-dd (for example 2014-02-04 or 2000-12-24).
Advices
Use android.widget.DatePicker instead of Edittext for getting dates as input.
Never use any texts you got from user inputs directly in your query, but validate them before (see sql-injection).
Read some articles about how Strings are compared.
Try SELECT * FROM "your table" WHERE date BETWEEN "from date" AND "to date";
you need to store date inform of yyyy-mm-dd and then use this method simply call getWeekData(start_date, end_date);
public Object getWeekData(String start_date, String end_date) {
if (!mDataBase.isOpen())
openDataBase();
Object data = new Object ();
// Select All Query
String query = (String) ("Select * from " + TBL_NAME
+ " where " + (COL_DATE + " between '" + start_date + "' AND '" + end_date + "'"));
Cursor cursor = mDataBase.rawQuery(query, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
//get data over here
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
close();
return data;
}
we have Two solution for this question
one is we need to convert date and time into milliseconds, and take long data type in
Sqllite database and save values(converted date and time). And the write query like "SELECT
data, start_date, end_date from tablename WHERE start_date > end_date".
Second way is you need to save start and end date+time(yyy-MM-dd HH:mm:ss) in string format
in Sqllite database, and you need to query like this,
"SELECT datetime_start,datetime_end FROM tablename WHERE(( DATETIME(atetime_start) >=
DATETIME ("+"'"+entry_start_time+"'"+")" +" AND DATETIME(datetime_end) < DATETIME
("+"'"+entry_end_time+"'"+")); .

Categories

Resources