Column columnname is not unique(code 19) - android

this is the code where I am trying to insert into my table and getting an exception that column ShopName(COL_SN) is not unique though I am giving a name that is not already existing in the database.That particular column is the primary key of the table
public void insert(String sn,String skn,String sa,String un,String pwd) throws SQLiteConstraintException
{
sdb=this.getWritableDatabase();
System.out.println("in insert method");
//sdb.execSQL("insert into " + TABLE_ShopDetails + " values(" +sn+ "," +skn+ "," +sa+ "," +un+ "," +pwd+ ")");
ContentValues cv=new ContentValues();
cv.put(COL_SN,sn);
cv.put(COL_SKN,skn);
cv.put(COL_SA,sa);
cv.put(COL_UN,un);
cv.put(COL_PWD,pwd);
sdb.insert(TABLE_ShopDetails,COL_SN,cv);
sdb.insert(TABLE_ShopDetails,COL_SKN,cv);
sdb.insert(TABLE_ShopDetails,COL_SA,cv);
sdb.insert(TABLE_ShopDetails,COL_UN,cv);
sdb.insert(TABLE_ShopDetails,COL_PWD,cv);
}

just call insert only once
sdb.insert(TABLE_ShopDetails,null,cv);

You should call insert() only once.
The ContentValues object already contains the values for all columns. By inserting multiple times, you're trying to create duplicate records, which results in a primary key violation.
The second parameter can be null, it's only for special cases (when values is empty).

You definitely only need to call insert once as others have said. The second optional parameter should most likely be null, it is for the following ...
optional; may be null. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided values is empty, no column names are known and an empty row can't be inserted. If not set to null, the nullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where your values is empty.
Also you might want to look into setting up a content provider. The link below would serve as a great tutorial.
Android SQLite database and content provider - Tutorial

Related

Input Validation, how can i enter unique name

I have coded a qr reader system and there are some part that I want to correct.
ContentValues values = new ContentValues();
values.put(BeneficiaryContract.BeneficiaryEntry._ID, beneficiary.getId());
values.put(BeneficiaryContract.BeneficiaryEntry.COLUMN_BENEFICIARY_NAME,
beneficiary.getName());
values.put(BeneficiaryContract.BeneficiaryEntry.COLUMN_BENEFICIARY_EMAIL,
beneficiary.getEmail());
values.put(BeneficiaryContract.BeneficiaryEntry.COLUMN_BENEFICIARY_DATE,
beneficiary.getDate());
values.put(BeneficiaryContract.BeneficiaryEntry.COLUMN_BENEFICIARY_ADDRESS,
beneficiary.getAddress());
values.put(BeneficiaryContract.BeneficiaryEntry.COLUMN_BENEFICIARY_COUNTRY,
beneficiary.getCountry());
Here is my inserting codes. but I want that not to insert same name. I have to block insertion two same name.
Can you please help me?
One way to enforce a unique beneficiary name would be to add a unique constraint to the corresponding column in your table. Then, any attempts to add a duplicate beneficiary name would fail at the database level, resulting in an exception in Java code, which you could catch and handle appropriately. Unfortunately, you cannot add unique constraints to tables which already exist, so you would have to recreate your beneficiary table with a unique constraint. In any case, the following CREATE TABLE statement would hopefully give you an idea of how to proceed:
CREATE TABLE BeneficiaryContract (
BENEFICIARY_NAME VARCHAR NOT NULL,
BENEFICIARY_EMAIL VARCHAR NOT NULL,
BENEFICIARY_DATE VARCHAR NOT NULL,
BENEFICIARY_ADDRESS VARCHAR NOT NULL,
BENEFICIARY_COUNTRY VARCHAR NOT NULL,
CONSTRAINT beneficiary_name_unique UNIQUE (BENEFICIARY_NAME)
);

SQLiteException: unrecognized token: "\":

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);";

Using insertWithOnConflict for update or insert

I need to insert or update and I found the method insertWithOnConflict of the SQLiteDatabase, but I do not know how it checks if the entry already exists.
Theoretically I need a "Where" argument to check if a certain ID exists, and if so, it should replace all other columns.
This is what I have now, but I don´t think that the second argument is the unique id
ContentValues args = new ContentValues();
args.put(AppDatabase.COLUMN_ID, entry.getId());
args.put(AppDatabase.COLUMN_NAME, entry.getAppname());
args.put(AppDatabase.COLUMN_URL, entry.getAppUrl());
database.insertWithOnConflict(AppDatabase.TABLE_FILELIST, COLUMN_ID, args, SQLiteDatabase.CONFLICT_REPLACE);
How can I manage this behaviour?
Make sure you have some appropriate constraint in your table, such as PRIMARY KEY or UNIQUE.
When inserting, add a value to this constrained column via ContentValues. If inserting the new row would violate some constraint, the conflicting rows are first deleted and then the new row is inserted.
In your case, COLUMN_ID looks like a good candidate for PRIMARY KEY constraint. The second arg nullColumnHack with value COLUMN_ID in your code is not necessary, you can pass it as null.

android update database column based on the current column value

In android, SQLiteDatabase has a update function
update(String table, ContentValues values, String whereClause, String[] whereArgs)
new values in put in values
If I want to update a column A by adding one to it, how should I prepare the ContentValues values variable? I don't think the following would work.
cv.put("A", "A" + 1);
I can sure run execSQL with raw sql, but it does not return num of row updated
If you'd execute a raw query, something like this should work to increment the current value in the column:
UPDATE table_name SET column_a = column_a + 1 WHERE _id = 1
(where 1 is just an example to illustrate how to apply it to a specific row)
The same probably wouldn't work with ContentValues, since (as the name indicates) it takes the values to set the column to. That means it needs to have been evaluated before building the ContentValues, whereas with a raw query the value isn't evaluated until the query actually runs on the database.
You can of course retrieve the current value first and then increment that accordingly when issuing an update; that requires a select query first. Quite commonly though, you're working with objects in Java, where the column value for a row is bound up to a member field of the object. If you've got a setup like that, then you probably already have the current value at the moment you want to run an update query.
As such, it would just look somewhat like:
SomeObject object = ...;
cv.put("column_a", object.getSomeValue() + 1);
(where I'm assuming object.getSomeValue() will return an int)
// edit: here's some more examples for the raw query approach:
SQLite - increase value by a certain number
// edit2: You've edited your original question and added:
I can sure run execSQL with raw sql, but it does not return num of
row updated
If knowing how many rows the query changed is a must, then you can potentially leverage the changes() function. It still means you're going to have to run a second query though.
SELECT changes() FROM table_name
The docs say:
The changes() function returns the number of database rows that were
changed or inserted or deleted by the most recently completed INSERT,
DELETE, or UPDATE statement, exclusive of statements in lower-level
triggers. The changes() SQL function is a wrapper around the
sqlite3_changes() C/C++ function and hence follows the same rules for
counting changes.
Alternatively, you could look into the rawQuery() method that takes an SQL statement and returns the result as a Cursor. Not sure if it that even works for an update query, or whether the result would be anything sensible, but if you're really lucky, you may find that Cursor.getCount() gives you the number of affected rows.
To expand upon #MH's solution, there actually is a way to do a raw update AND get back the number of rows updated (because I'm doing the same thing in one of my projects). You have to use a compiled SQLiteStatement and then call the method executeUpdateDelete(). From the documentation:
public int executeUpdateDelete ()
Execute this SQL statement, if the the number of rows affected by execution of this SQL statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
Returns
the number of rows affected by this SQL statement execution.
See the following sample code where I add a new column to my table and then update each column similarly to how you were asking:
db.beginTransaction();
try {
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN "
+ COLUMN_NAME_LOCALTIME + " INTEGER");
String stmtString = "UPDATE " + TABLE_NAME + " SET "
+ COLUMN_NAME_LOCALTIME + "="
+ COLUMN_NAME_TIME + "+ (" + tzOffset + ")";
SQLiteStatement sqlStmt = db.compileStatement(stmtString);
int rows = sqlStmt.executeUpdateDelete();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
I'm using a transaction here because in case I add the new column but CANNOT update the values, I want everything to rollback so I can attempt something else.

Android Sqlite INSERT error when table contains only _id

I have a SQLite table that contains only the _id:
"create table rule (_id integer primary key);";
When running this set of commands:
ContentValues initialValues = new ContentValues();
mDb.insert(TABLE, null, initialValues)
I obtain the following exception:
android.database.sqlite.SQLiteException: near "null": syntax error (code 1): , while compiling: INSERT INTO rule(null) VALUES (NULL)
The initial error occurs because ContentValues cannot be empty. Android provides a convenience parameter called nullColumnHack that allows you to pass a single column with the value null, to bypass this problem.
However this doesn't apply in my case because the row id (_id) cannot be null! Based on the syntax found in the SQLite language docs, I would like to be able to run the SQLite code:
INSERT INTO rule DEFAULT VALUES;
How can i achieve something like this using the android insert method? Or is there something I need to add to my create statement?
UPDATE: In the situation where a table contains ONLY a rowid, the proper syntax is to use INSERT INTO __ DEFAULT VALUES.
The sqlite insert method listed in android does not support DEFAULT VALUES as an option.
A bug has been filed with google and to get support for default values the following commands would need to be executed:
mDb.execSQL("INSERT INTO rule DEFAULT VALUES;");
Cursor c = mDb.rawQuery("SELECT last_insert_rowid()",null);
c.moveToFirst();
int rowid = c.getInt(0);
As stated in the accepted answer, we can get around this (and DEFAULT VALUES) by using nullHackColumn and assigning the row id (_id) to null and letting SQLite make the conversion from null to the auto-incremented value.
As jeet mentioned you can provide nullColumnHack as a second parameter. And as you yourself mentioned autoincrement isn't necessary to increment a value of primary key.
So the syntax:
insert into rule (_id) values(null)
where _id is primary key and autoincremented value is correct for sql. I think most SQL databases will replace null with new incremented value, at least MySQL, SQLite and Oracle can do this
Thus:
ContentValues cv = new ContentValues();
db.insert("rule", "_id", cv);
should give you desired results.
You need to add autoincrement to your create table query like:
"create table rule (_id integer primary key autoincrement);";
In your case you need to manually set the ID of the row with each insert. this way it will increment it automatically when you insert an empty row as you did in your case.
Try this way :
ContentValues initialValues= new ContentValues();
if(check here --id is null----)
{
initialValues.put("_id", "0");
}
else
{
initialValues.put("_id", id);
}
mDb.insert(TABLE, null, initialValues)
Check following:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insert(java.lang.String, java.lang.String, android.content.ContentValues)
SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided values is empty, no column names are known and an empty row can't be inserted. If not set to null, the nullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where your values is empty.
the insert needs a null value you just have to put
db.insert ("people", null, c);

Categories

Resources