I have looked through several sites for any useful documentation and have come up empty. The flow charts from the official site might as well be greek and examples I have attempted from other relevant posts on this site have gotten me errors. I am writing a simple app to place user input in a database, however I need a combination of 2 columns to be unique. From what I have seen this can be accomplished with UNIQUE or PRIMARY KEY. I also need some way of capturing the error to Toast the user that their input is faulty. I know that I can do this in the Java side easily enough yet I would prefer not to loop through the table on every proposed insert.
This is what I have so far:
db.execSQL("CREATE TABLE inventory (category TEXT, itemNum TEXT, quantity INTEGER, price REAL, image INTEGER, UNIQUE(category, itemNum) ON CONFLICT FAIL;");
The table constructed properly until I added UNIQUE...
Which threw:
ERROR/SQLiteOpenHelper(1037): android.database.sqlite.SQLiteException: near ";": syntax error: CREATE TABLE inventory (category TEXT, itemNum TEXT, quantity INTEGER, price REAL, image INTEGER, CONSTRAINT unq UNIQUE(category, itemNum) ON CONFLICT FAIL;
EDIT:
... fill ContentValues values with user input.
try{
db.getWritableDatabase().insert(DatabaseHelper.TABLE_NAME, DatabaseHelper.CATEGORY, values);
fillItemNumbers(); // Updates screen
}
catch(SQLiteConstraintException e)
{
Toast
.makeText(this, "User error",Toast.LENGTH_LONG)
.show();
}
You have mismatched parenthesis. There should be another ) after FAIL.
Once you've sorted that, you can catch the exception that happens when the constraint is breached.
try {
// insert new data
} catch (SQLiteConstraintException e) {
Toast.makeText(context,
"The combination of A and B must be unique",
Toast.LENGTH_LONG).show();
}
Related
Here is the table where i want to insert the value:
" create table if not exists "+CipherCongfigTable +
" ( DATABSE_NAME **TEXT** PRIMARY KEY NOT NULL,DATABSE_KEY **TEXT** NOT NULL);";
when i want to insert
String **configDBPassword**= "**x\'2DD29CA89\'**"
through statement
"insert into "+CipherCongfigTable+ " values("+DataBaseName+","+**configDBPassword**+")"
I am getting exception:
unrecognized token: "\":
I need the password in the same format i.e. having escape charecter. Is there any way to do it????
Thanks
Don't manually build INSERT (or any other if you can avoid it) queries on Android (or any other database wrapper as long as there is a predefined API to get what you want). It opens up your application to quoting problems like the one from your question and --at the worst-- to SQL injection attacks from outside of your application.
For example, setting configDBPassword = "\"; DROP TABLE <tablename>; --" I could possibly wreak havoc on your database as long as configDBPassword can be entered by the user.
Also, SQLite uses double quotes ("), backticks (`, borrowed from MySQL), or square brackets ([], borrowed from MS SQL) to quote identifiers (e.g. column or table names with spaces in them), string literals are canonically quoted with single (') quotes. SQLite is a quite liberal in allowing to mix both quoting types, but it is significantly more readable to use the proper quoting style whereever appropriate. From the documentation:
Programmers are cautioned not to use the two exceptions described in the previous bullets. We emphasize that they exist only so that old and ill-formed SQL statements will run correctly. Future versions of SQLite might raise errors instead of accepting the malformed statements covered by the exceptions above.
As a matter of fact, you should avoid doing the quoting by yourself whenever possible. For inserting values, please instead use SQLiteDatabase.insert() which is the proper way of inserting values into an SQLiteDatabase on Android. It also does proper quoting of the arguments, too:
db.beginTransaction();
try {
final ContentValues values = new ContentValues();
values.put("DATABSE_NAME", DataBaseName);
values.put("DATABSE_KEY", configDBPassword);
db.insert(CipherCongfigTable, null, values);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
Always properly quote your SQL parameters.
Try this .
"INSERT INTO "+CipherCongfigTable+ " values('DataBaseName','configDBPassword')”
You are not adding Single quotes(') in your insert query
Edit :
If you need to insert string with Single qotes means use like this before insert.
configDBPassword = configDBPassword.replace ("'", "''");
Also change your **
" create table if not exists "+CipherCongfigTable +
" ( DATABSE_NAME TEXT PRIMARY KEY NOT NULL,DATABSE_KEY TEXT NOT NULL);";
I'm new to coding android apps with Sqlite
I have three questions
I created this Sqlite table with columns with attributes like
TEXT
NOT NULL
UNIQUE
DEFAULT regular
Q1) I'm skeptical to know whether is there any order on how to delare attributes for a row
Q2) If I declare any row to have a default value like will the text be still inserted even though the user inserts something in that row, if yes, then how to insert a default value if the user dosen't inset any value in a specific Row
Q3)Is my code below correct ? What I desire is the row KEY_TAGNAME to be unique, not null and to have a value if the row doesn't get any data while a insert statement occurs for that table.
private static final String CREATE_TAGTABLE_SQL=
"CREATE TABLE " + DATABASE_TABLE_TAG
+ " ("
+ KEY_TAGROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ KEY_TAGNAME + " TEXT NOT NULL UNIQUE DEFAULT regular"
+ ");";
A1: I couldn't find anything in the documentation that clearly says anything about the order of the attributes but I tried to create a couple of tables in a test database I created to check this and it seems that if you do not follow the proper order you will get a syntax error.
(tried with create table test (key1 integer primary key autoincrement) which works correctly but create table test1 (key1 primary key integer autoincrement) gives a near "integer": syntax error:
A2: You can have a default value inserted that will be put if the user does not input anything there. The keyword is default and you will find more info here on how to use it (TL;DR upon table's creation you will create the row as usual and in the end put a DEFAULT and next to it the value. Please check the link on this)
A3 Your query is correct and will do the things you mention.
i am running a query that looks like this
SELECT SUM(KILLCOUNT),SPECIES.SPECIES
FROM TRIP_DATA JOIN SPECIES
ON TRIP_DATA.SPECIES=SPECIES.SPECIESIDNO
where TRIP_DATA.TRIPID=413
group by TRIP_DATA.SPECIES.
for this trip (413) I ma getting the output, 2 hares and 6 rabbits, however I have only entered 1 hare and 3 rabbits in the database. I cannot see why I am returning double the amount I want. Any advice or corrections to my understanding would be greatly received
for completeness I attach the create statements on the two tables I am joining
"CREATE TABLE IF NOT EXISTS "
+TRIP_DATA
+" (ID INTEGER PRIMARY KEY AUTOINCREMENT,TRIPID INTEGER NOT NULL,GMTTIMESTAMP INTEGER NOT NULL,LATITUDE REAL NOT NULL," +
"LONGITUDE REAL NOT NULL, ALTITUDE REAL,ACCURACY REAL,SPEED REAL,SPECIES INTEGER,KILLCOUNT INTEGER);
and
CREATE TABLE IF NOT EXISTS "+
SPECIES+
" (SPECIES TEXT NOT NULL,ISHUNTED INTEGER NOT NULL DEFAULT (1),SPECIESIDNO INTEGER NOT NULL, EXPANSION TEXT);"
After some time and research this is the answer that I was looking for
SELECT DISTINCT SPECIES.SPECIES,S.COUNT
FROM SPECIES
INNER JOIN
(
SELECT SUM(KILLCOUNT) AS COUNT,TRIP_DATA.SPECIES
FROM TRIP_DATA
WHERE TRIPID="+tripid+" AND NOT TRIP_DATA.SPECIES =0
GROUP BY TRIP_DATA.SPECIES
)S
ON SPECIES.SPECIESIDNO=S.SPECIES
As I understand it (please be aware that this is at the limits of my understanding) when you do an inner join the aggregate functions work on the both primary keys of the joined tables.
this means that my original approach was never going to work, however if make a inner statement using the group buy and use the on word to add the data to the already grouped table it works
many thanks for the comments, I hope helps someone else
I have a table with 4 fields: _id, to, from, hidden
Upon trying to insert the following values:
_id=167 from=1311005879000 to=1311005879000 hidden=0
into my table, I got an SQLiteConstraintException stating that
'column _id is not unique (code 19)'
To find the cause for this problem I tried querying the size of the table and found it is 0, so I have no idea where this is coming from.
Maybe I didn't understand the error correctly?
Edit: some code!
try {
mDatabase.insertOrThrow("groups", null,
mContentValues);
} catch (SQLException e) {
e.printStackTrace();
}
Creation SQL:
CREATE TABLE IF NOT EXISTS groups(_id LONG PRIMARY KEY,hidden INTEGER,from LONG,to LONG
'column _id is not unique (code 19)'
So you are violating UNIQUE Constraint. This is reason of SQLiteConstraintException. Your _id column is most likely primary key and primary keys have implicitly assigned UNIQUE constraint that say no two rows can have same primary key.
You are trying to insert duplicit _id that already is in db or PK is assigned to NULL.
I tried querying the size of the table and found it is 0, so I have no
idea where this is coming from.
I think your query was broken because your Exception says everything and it cannot be thrown if somewhere is not a problem.
Update:
If you are not assigned NULL to PK and also your table has 0 records probably problem is here:
mDatabase.insertOrThrow("groups", null, mContentValues);
You are assigned NULL to ColumnHack as second param of insert() method that you shouldn't. In SQLite, each row must have at least one column specified. It needs one column that can be safe assigned to NULL.
This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
sqlite example program in android
Hi I'm new to android and I am having some trouble finding a good tutorial for an SQLite database. What I wanted to do was to store a line of data in the database, reference it later and then delete it once its been referenced. As I have said I am new to this sort of thing and have no clue even what any of the syntax is so if there is a simple tutorial out there I would like to know.
try this
try { // creating a database called db and a Table inside it, called
// userdetails. With username and password as columns.
db = openOrCreateDatabase("UserDetails.db",
Context.MODE_PRIVATE, null); // optional CursorFactory
db.execSQL("drop table if exists userdetails");
db.execSQL("create table userdetails " + " ( username TEXT,"
+ "password TEXT);");
} catch (SQLException x) {
x.printStackTrace();
Log.e(LOG_TAG_NAME, "Database creation error");
}
//.........................................................................
// and insert values into the database table.
try {
db.execSQL("INSERT INTO " + "userdetails"
+ " (username,password)" + " VALUES ('hi','hello');");
db.execSQL("INSERT INTO " + "userdetails"
+ " (username,password)" + " VALUES ('chris','gayle');");
db.execSQL("INSERT INTO " + "userdetails"
+ " (username,password)" + " VALUES ('v','v');");
} catch (Exception e) {
e.printStackTrace();
Log.e(LOG_TAG_NAME, "inserting table values error");
}
String[] columns = { "username", "password" };
Cursor c = db.query("userdetails", columns, null, null, null, null,
null);
now use the cursor to retrieve values
also have a look at
http://developer.android.com/guide/topics/data/data-storage.html#db
hope all this helps
EZ Answer I think.
If I understand your needs I think that you will find a database is overkill. You can do this a lot easier I think with just a few lines of code. If I am correct, a "line of data" sounds like a single String that you want to persist. If that is the case SharedPreferneces is by far your best bet for easy implementation.
Check out THIS link to the Dev-Guide's Shared Preferences Data Storage section
Its as easy as initializing the Preferences, and either putting or asking for a value by key.
On the other hand if you need to store many lines of relational data, search through them, sort them, etc. then a database is what you want.
Generally, I choose the data storage mechanism based on what is being stored and how i want to retrieve it:
Single primitives (and Strings) get stored best in SharedPreferences.
This is a fast and easy implementation. You can get away with storing a couple of values if you need to to represent a more complex class. Sometimes it makes sense to create a helper class that keeps track of complex schemes.
Serializable complex data, like parameterized Collections, that are loaded into memory all at once, long streams of text to be parsed, or if that data is a byte stream it gets stored to a file. This is not as fast and involves catching a lot of potential IO issues. But most objects are serializable or easily made that way.
Tables of data that I want to query or provide a Cursor for because of how long they are go into a database. The start up and resource expenses of a database are huge. Writing all the helper code to use them is a pain in the extreme.
Complete Step by Step SQLite Example:
http://mobile.tutsplus.com/tutorials/android/android-sqlite/
Youtube Video Tutorial
http://www.youtube.com/watch?v=kMaBTolOuGo
Multiple Table Creation
http://androidforbeginners.blogspot.com/2010/01/creating-multiple-sqlite-database.html
PS: All the links are tested and working well!!
Happy Coding!!
First place to look for tutorials should be the official Android Docs: Link.