I am trying to prevent duplicate entries into my sqlite db by using the UNIQUE identifier when creating a table. The information, including the primary key, is inserted via some json data returned from a web service.
Whilst I understand the implications of not using an auto-generated primary key, it is necessary for the business model.
If by chance the web service returns a record which already exists then you would assume that it would not insert the data again, but throw an error. This is not the case.
Does anyone know a way to prevent this from happening?
Creation statement
CREATE TABLE "Data" ("Id" INTEGER PRIMARY KEY NOT NULL UNIQUE , "DataText" TEXT NOT NULL , "CategoryId" INTEGER NOT NULL )
Insert code
if (sqlite3_open([[self getDatabaseConnection] UTF8String], &database) == SQLITE_OK)
{
const char *sql = "INSERT INTO Data (Id, CategoryId, DataText) Values(?, ?, ?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStatement, NULL) != SQLITE_OK)
{
NSLog(@"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
else
{
sqlite3_bind_int64(addStatement, 1, dataId);
sqlite3_bind_int64(addStatement, 2, categoryId);
sqlite3_bind_text(addStatement, 3, [dataText UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(addStatement))
{
NSLog(@"Error while inserting data. '%s'", sqlite3_errmsg(database), nil);
}
}
//Reset the add statement.
sqlite3_reset(addStatement);
}
sqlite3_close(database);
Let’s say you have a table called PRODUCTS and it contains this value:
ProductID is the primary key.
Unless you have a unique index on [productname] you could insert this record:
But even if you did not have a unique index on productname, you could not insert any additional records with a productid of 50, no matter what the product’s name happened to be, because a row with primary key value of 50 already exists.
ADDENDUM:
Now let’s say that you were willing to accept multiple instances of ‘widget’ but not within the same category. You could have “roofing widget” and “flooring widget”. In that case, in addition to the primary key unique constraint on your integer id column, you could place a unique constraint on this alternate composite key: (productname, categoryid).
ADDENDUM2:
INTEGER PRIMARY KEY should suffice. You shouldn’t need NOT NULL UNIQUE. http://www.sqlite.org/lang_createtable.html#rowid