I have got the error message " or expected, got 'Index'" when I was trying to create a table and I do not really understand why is the code expecting a column definition or table constraint at this line
I have tried with changing the whitespaces, however that only change the place where the error is prompted. The content of the error message does not change
This is the part that I have declared the strings
public class TaskEntry implements BaseColumns {
public static final String TABLE = "Users";
public static final String INDEX = "Index";
public static final String COL_TASK_TITLE = "title";
}
The following is my code for the creating table part
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + Item_contract.TaskEntry.TABLE + " ( " +
Item_contract.TaskEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
Item_contract.TaskEntry.INDEX + " INTEGER NOT NULL, " +
Item_contract.TaskEntry.COL_TASK_TITLE + " TEXT NOT NULL" + ");";
db.execSQL(createTable);
}
You cannot use INDEX as a column name as it is a keyword.
The SQL standard specifies a large number of keywords which may not be
used as the names of tables, indices, columns, databases, user-defined
functions, collations, virtual table modules, or any other named
object. The list of keywords is so long that few people can remember
them all. For most SQL code, your safest bet is to never use any
English language word as the name of a user-defined object.
SQL As Understood By SQLite - SQLite Keywords
So change
public static final String INDEX = "Index";
perhaps to
public static final String INDEX = "IX";
You could enclose the column name if you really wanted it to be INDEX e.g.
public static final String INDEX = "[Index]";
As per :-
If you want to use a keyword as a name, you need to quote it. There are four ways of quoting keywords in SQLite:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not standard SQL. This quoting mechanism is used by MS Access and SQL Server and is included in SQLite for compatibility.
`keyword` A keyword enclosed in grave accents (ASCII code 96) is an identifier. This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.
SQL As Understood By SQLite - SQLite Keywords
Note
You will have to do one of the following to get the onCreate method to run and thus alter the schema:-
Delete the App's data.
Uninstall the App.
Related
This is my db helper class, that creates a db when the app is installed the first time.
When I register a new user, if his name is letters like "john", it gives me an exception.
However, usernames like 4, 56 (i.e.: digits only) give no errors. Why?
class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "myDB", null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d("x", " database CREATED!!! -------------------------");
db.execSQL("create table userData ("
+ "id integer primary key autoincrement,"
+ "name text,"
+ "password text,"
+ "hero int,"
+ "level int,"
+ "loggedin int"
+ ");");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
EDIT:
This is the piece of code where I actually try to update my db.
public void login(View v){
//..some code here
db.execSQL("update userData set loggedin=1 where name=" + username2) ;
}
All strings in sql must be enclosed by '. Quoted from https://www.sqlite.org/lang_expr.html:
"A string constant is formed by enclosing the string in single quotes ('). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL."
if his name is letters like "john", it gives me an exception.
However, usernames like 4, 56 (i.e.: digits only) give no errors. Why?
Wild Guess: You forgot to enclose John in single quotes, i.e.: 'John'.
The reason for this being that John is a string.
And strings must be delimited by single quotes (')
Be aware that, if the string itself contains a quote (or apostrophe), i.e. 'I'm aware of that', then the apostrophe it has to be doubled, i.e. 'I''m aware of that'.
If you don't want to hassle with quotes, there's a better way to make Android handle it for you: bound parameters.
In practice, all the values in your query should be replaced by a question mark placeholder (?).
And you give the query a String array containing all the values to be replaced.
This way you are also protected against SQL injection.
An example would clarify the concept better:
// Two values to be passed...
final String sql =
"SELECT date, score FROM " + DB_TABLE +
" WHERE strftime('%Y', date) = ? AND " +
"CAST((strftime('%m', date)) AS INTEGER) = ? ORDER BY date DESC";
// ... into the string array parameter of the rawQuery() overload
final Cursor cur =
db.rawQuery
(
sql,
new String[]
{
String.valueOf(CLS_Utils.yearUsing),
String.valueOf(month)
}
);
Note.
The same technique applies to execSQL() as well.
Therefore it can be used on INSERTs, UPDATEs and DELETEs as well.
How to check if data queried from android sqlite database is empty in a bindView method?
This is what I have done so far, but I think I am doing the wrong thing.
UPDATE
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
SQLiteDatabase db;
db = openOrCreateDatabase(
"no.db"
, SQLiteDatabase.CREATE_IF_NECESSARY
, null
);
//CREATE TABLES AND INSERT MESSAGES INTO THE TABLES
String CREATE_TABLE_NOTICES = "CREATE TABLE IF NOT EXISTS notices ("
+ "ID INTEGER primary key AUTOINCREMENT,"
+ "NOT TEXT,"
+ "DA TEXT)";
db.execSQL(CREATE_TABLE_NOTICES);
Cursor myCur = null;
// SQLiteDatabase db;
myCur = db.rawQuery("SELECT ID as _id,NOT,DA FROM notices order by ID desc", null);
mListAdapter = new MyAdapter(Page.this, myCur);
setListAdapter(mListAdapter);
}
#Override
public void bindView(View view, Context context, Cursor myCur) {
TextView firstLine=(TextView)view.findViewById(R.id.firstLine);
if(myCur==null){
String message="No Message";
firstLine.setText(message);
}
}
The keyword NOT is a reserved word in MySQL. I'd be very surprised if it's not a reserved word in SQLite.
I think the problem is here:
SELECT ID as _id,NOT,DA FROM notices order by ID desc
-- ^^^
It looks like the reserved word NOT is being used as a column name. To use that as an identifier, it will need to be "escaped", by enclosing it in backtick characters.
SELECT ID as _id,`NOT`,DA FROM notices ORDER BY ID DESC
-- ^ ^
That's the normative pattern in MySQL. For SQLite, you use the (MySQL compatible ) backtick characters, or you can use double quotes (more ANSI standard compliant.)
It's also possible to qualify the column name. (I'm certain this works in MySQL).
SELECT n.ID AS `_id`, n.NOT, n.DA FROM notices n ORDER BY n.id DESC
-- ^^ ^^ ^^ ^ ^^
References:
MySQL Reference Manual: 9.3 Keywords and Reserved Words https://dev.mysql.com/doc/refman/5.5/en/keywords.html
Certain keywords, such as SELECT, DELETE, or BIGINT, are reserved and require special treatment for use as identifiers such as table and column names.
SQLite: SQLite Keywords https://www.sqlite.org/lang_keywords.html
If you want to use a keyword as a name, you need to quote it. There are four ways of quoting keywords in SQLite:
It may also be a problem in the CREATE TABLE statement. Since you are creating the table, you have the option of using a different name for the column, a name which is not a reserved word.
I got an app that as an internal database, and the app crashes with this error :
04-30 20:46:30.836 1647-1647/prosis.guiatour E/SQLiteLog﹕ (1) no such column: Basílica_Santa_Luzia
and the code that this is refering to is :
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_QUERY);
Log.e("Database Operations"," Table Created....");
db.execSQL(addingInfo("Basílica_Santa_Luzia", "Stuff", "10.43597", "-10.5747"));
Log.e("Database Operations"," Data Inserted");
}
public String addingInfo(String nome, String cat, String lat, String longi){
String Query = "INSERT INTO "+ Table_name+" VALUES("+nome+","+cat+","+lat+","+longi+");";
return Query;
}
And this is my contructer query :
private static final String CREATE_QUERY = "CREATE TABLE "+ Contract.NewLocalInfo.Table_name+" ("+ Contract.NewLocalInfo.Nome+" TEXT,"+ Contract.NewLocalInfo.Categoria+" TEXT,"+ Contract.NewLocalInfo.Latitude+" TEXT,"+ Contract.NewLocalInfo.Longitude+" TEXT);";
I think the SQL is well Writen so what do you think is the problem here?
Your SQL would not be valid. Based on your function, you would get:
INSERT INTO table_name VALUES(Basilica_Santa_Luzia,Stuff,10.43,10.57)
which is not valid. You have to single-quote strings like:
INSERT INTO table_name VALUES('Basilica_Santa_Luzia','Stuff','10.43','10.57')
But, you should not be writing any SQL unless you have complex requirements. You should use what's built into Android or get a third-party option.
Writing an SQL Query string creates security risks and causes errors like this one.
To insert, instead do:
ContentValues cv = new ContentValues();
cv.put("key","value");
cv.put("key2","value2");
db.insert("table_name",cv);
This approach will automatically escape any paramaters and guarantee that your query is not erroneous.
Also, the latitude and longitude probably should not be Strings. I don't remember for sure, but what I think you need is double for the Java/Android side and in normal SQL, you would need a decimal datatype on the column, but its SQLite and I'm not sure what you're supposed to do for a decimal column in sqlite, so maybe Duck it.
Also, I made a database manager class which wraps the SQLiteOpenHelper class to ensure synchronization and thread safety, which can simplify your life a ton and prevent tons of errors.
Add single quote around all values then this insert will work. Final query should be like below
INSERT INTO TABLE_NAME VALUES('Basílica_Santa_Luzia','Stuff','10.43597','-10.5747');
I'm developing an Android application and i'm using a Sqlite database to store some bitmaps. I want some images to be automatically inserted when the user installs the application.
I'm using the SQLiteOpenHelper class like this:
public class DatabaseHelper extends SQLiteOpenHelper {
...
DatabaseHelper(Context context, String nameOfDB, int version, String[] scriptSQLCreate,
String scriptSQLDelete) {
super(context, nameOfDB, null, version);
this.scriptSQLCreate = scriptSQLCreate;
this.scriptSQLDelete = scriptSQLDelete;
}
#Override
public void onCreate(SQLiteDatabase db) {
int numScripts = scriptSQLCreate.length;
for(int i = 0; i<numScripts; i++){
Log.i(TAG,"Creating database, executing script " + i);
db.execSQL(scriptSQLCreate[i]);
}
}
}
...
I want to pass a constant to the scriptSQLCreate parameter shown above that would be like so:
private static final String[] SCRIPT_DATABASE_CREATE = {
"create table memes( id integer primary key autoincrement," +
+ " img blob not null," +
+ " name text not null unique)" ,
"insert into memes(img,name) values(BITMAP1,'1.jpg')",
"insert into memes(img,name) values(BITMAP2,'2.jpg')",
"insert into memes(img,name) values(BITMAP3,'3.jpg')"}
}
Any help will be much apreciated,
Thx,
Tulio Zahn
If you really, really want to you can use a very long hex literal as a blob literal:
insert into memes(img, name) values(X'0102030405060708090a0b0c0d0e0f', '1.jpg')
However, this is usually a bad idea; instead, go look at parameterised queries. They will let you compile a statement once using placeholders instead of actual values, and then reuse it many times, filling in the placeholders as needed:
SQLiteStatement p = sqlite.compileStatement("insert into memes(img, name) values(?, ?)");
byte[] data = loadData("1.jpg");
p.bindBlob(1, data);
p.bindString(2, "1.jpg");
p.execute();
byte[] data = loadData("2.jpg");
p.bindBlob(1, data);
p.bindString(2, "2.jpg");
p.execute();
(Warning --- code not tested.)
In general you should be using parameterised queries everywhere, as they're a sure-fire way to avoid SQL injection attacks, plus are usually easier and clearer. Assembling SQL queries by glueing strings together should be avoided at all costs.
Your data table has some invisible word which you can not see. Check your db file with the db tools like navicat for sqlite. Please pay attention to the error word in the table.
I have read most of the questions related to this exception but none of them are clear or indicative of why db.insert would throw this error. It was working fine without errors until I manually deleted the db from DDMS. Following is my SQLiteOpenHelper code:
public class LoginSQLiteOpenHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "logincredentials.sqlite";
public static final int DB_VERSION_NUMBER = 1;
public static final String DB_TABLE_NAME = "credentials";
public static final String USERNAME = "user_name";
public static final String PASSWORD = "password";
private static final String DB_CREATE_SCRIPT = "create table " + DB_TABLE_NAME +
"( _id integer primary key autoincrement," +
USERNAME + " text not null, " +
PASSWORD + " text not null );" ;
public LoginSQLiteOpenHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION_NUMBER);
}
#Override
public void onCreate(SQLiteDatabase aSqliteDB) {
Logger.d("Create", "Creating the database...");
aSqliteDB.execSQL(DB_CREATE_SCRIPT);
}
}
My code for inserting the values is:
ContentValues contentValues = new ContentValues();
contentValues.put(LoginSQLiteOpenHelper.USERNAME, loginId);
contentValues.put(LoginSQLiteOpenHelper.PASSWORD, password);
database.insert(LoginSQLiteOpenHelper.DB_TABLE_NAME, null, contentValues);
This is why it occurred to me. If you declare one of your column name type as UNIQUE in your Create Table query in Database and try to insert a non unique variable, it invokes SQLiteConstraintException error.
A UNIQUE constraint is similar to a PRIMARY KEY constraint, except that a single table may have any number of UNIQUE constraints. For each UNIQUE constraint on the table, each row must feature a unique combination of values in the columns identified by the UNIQUE constraint. As with PRIMARY KEY constraints, for the purposes of UNIQUE constraints NULL values are considered distinct from all other values (including other NULLs). If an INSERT or UPDATE statement attempts to modify the table content so that two or more rows feature identical values in a set of columns that are subject to a UNIQUE constraint, it is a constraint violation. Source - http://www.sqlite.org/lang_createtable.html
I have read pretty much all forums looking for an exact reason for the occurrence of this exception. However, nowhere it clearly states so. However, by means of this code of mine, I can explain why it ocurred for me.
The code snippet I provided, is actually flawless. I am doing exactly what is required to do a db.insert().
However, i figured out the exception in 2 steps.
1. first time when i inserted values, I did not insert a value for the column Password.
2. second time, I added a value for column for Password, but due to incorrect passing of values it was null.
hence, I deduced from this exercise, that no column are allowed null values. You must initialize them with some value.
Please feel free to comment/add or correct me if I am wrong. I would like anyone else running into this issue to be clear on it as there are no good documentation on this exception.