In eclipse as soon as i type this out:
BaseColumns._ID, + "=?"
I get:
The operator + is undefined for the argument type(s) String
How is that possible, they are both Strings aren't they?
now here is documentation for BaseColumns._ID:
public static final String _ID
the code I am writing is:
public void deteleProfile(Long id) throws SQLException {
SQLiteDatabase db = helper.getWritableDatabase();
Integer i = db.delete(ProlificDatabase.TABLE, BaseColumns._ID, + "=?", new String[] {id.toString()});
Log.d(TAG, i + " records deleted where id is " + id);
You've got a rogue comma:
BaseColumns._ID, + "=?"
should probably be
BaseColumns._ID + "=?
Otherwise it's trying to use + "=?" as a stand-alone argument with the + acting as a unary operator.
Do you mean BaseColumns._ID + "=?" instead of BaseColumns._ID, + "=?"?
The compiler just sees the left hand side of the + operator as being empty.
See this documentation on how to use the db.delete method. Instead of BaseColumns._ID, + "=?" - you should be doing this:
Integer i = db.delete(ProlificDatabase.TABLE, BaseColumns._ID + "=?", new String[] {id.toString()});
Lovely extra , (comma)... love the commas for what they are, meaning a separator between expressions and a pain ... for when you overlook them!
Related
I'm trying to add numeric values to parameterized AnalyticsQuery but keep getting errors when the query runs. The java creating the query looks like this:
private ParameterizedAnalyticsQuery aggregateQuery(String userId, Long from, Long to) {
return AnalyticsQuery.parameterized(
"select d.field1,"
+ " d.field2"
+ " from data d"
+ " where d.userId = $userId"
+ " and d.timestamp between $from and $to",
JsonObject.create()
.put("userId", userId)
.put("from", from)
.put("to", to)
);
}
When the query is run the following error is returned:
<< Encountered \"from\" at column 213. ","code":24000}]
If I change the query to the following then it works and returns rows:
return AnalyticsQuery.parameterized(
"select d.field1,"
+ " d.field2"
+ " from data d"
+ " where d.userId = $userId"
+ " and d.timestamp between " + from
+ " and " + to,
JsonObject.create()
.put("userId", userId)
);
Why is there a problem when the parameters are not Strings? Is there a way to use parameterized queries with numeric values?
FROM and TO are reserved keywords in N1QL for Analytics and therefore must be put in backquotes when used as parameter names:
... and d.timestamp between $`from` and $`to`
For a list of all reserved keywords please see:
https://docs.couchbase.com/server/current/analytics/appendix_1_keywords.html
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.
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.
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);
In the SQLite chapter of "Hello, Android", an interface Constants is created to hold some constant strings: the table name and field names.
Why? How is it more useful to use TITLE than "title" directly? Is there something else I'm missing?
And by the way: how should it be organized if I need two tables? Should I make FirstTableConstants and SecondTableConstants interfaces?
If you're going to use a string more than once, its best to create a constant for it.
It prevents creation of the string more than once.
Object allocation isn't free so you will see some performance gain.
Consider the case where you create the string in a loop.
for(int i=0;i<n;++i){
System.out.println("title");
}
vs using a constant:
for(int i=0;i<n;++i){
System.out.println(TITLE);
}
If it took 1ms to allocate the string "title", your run time for the first loop code is N X 1ms.
Also building SQL statements with constants will be quicker than repeatedly creating new strings for the statement keywords for types (text, integer,) modifiers (unique, not null), etc.
String TABLE_SCHEMA = "(" +
ID + " integer primary key autoincrement, " +
COL_FOO1 + " text, " +
COL_FOO2 + " text, " +
COL_FOO3 + " text, " + ...
If you make " text, " a constant you aren't creating that string over and over again, so your TABLE_SCHEMA string is created quicker.
String TABLE_SCHEMA = "(" +
ID + " integer primary key autoincrement, " +
COL_FOO1 + TYPE_TEXT +
COL_FOO2 + TYPE_TEXT +
COL_FOO3 + TYPE_TEXT + ...
If you're using a class, you should probably have them as public static final String TITLE = "Some Title" field. It's better to use it this way so that you won't make an error while typing it into a command. You'll only have to type the variable name.