I have a table with a composite primary key and I am having trouble inserting. The code used to create the table is:
CREATE TABLE ClassEvent (
EventName varchar(10) NOT NULL,
CourseId varchar(10) NOT NULL,
EventType varchar(20),
EventWeight number(3),
DueDate DATE NOT NULL,
FOREIGN KEY (CourseId) REFERENCES Courses(CourseId),
PRIMARY KEY (CourseId, EventName));
The problem I am having is when I want to insert records that have values that may not be unique for the columns CourseId or EventName, but are a unique combination of the 2.
for example, if I try to run the following 2 inserts:
INSERT INTO ClassEvent VALUES('Assignment 1','60-415','Assignment',10,'12/10/2010');
INSERT INTO ClassEvent VALUES('Project 1','60-415','Project',15,'5/12/2010');
I get the following error:
Error: columns CourseId, EventName are not unique.
and the second insert does not make it into the DB. Why does this error out? I thought that a composite primary key requires that the combination of both values are unique. In my above inserts, the values for the EventName column are different even though the values for CourseId are the same. Shouldn't this be seen as 2 unique combinations and thus 2 different primary keys?
My table needs to be able to hold several different events for each CourseId, but each Event must be unique for each Course. I need to be able to insert values into the table like:
EventName CourseId
Assignment 1 60-415
Project 1 60-415
Assignment2 60-415
Project 2 60-415
Assignment 1 60-367
Project 1 60-367
and so on. Can anyone tell me how I can get this to work? Why are these composite PK's not being seen as unique entries? Any help would be much appreciated.
Here is the java function I am using for the insert:
public void addNewClassEvent(ContentValues values) {
SQLiteDatabase db = openConnection();
db.insert("ClassEvent", null, values);
db.close();
}
Could this be causing the problem?
You can have a composite primary key in SQLite, but you
have to create the key when you create the table:
CREATE TABLE example1(
field1 FLOAT,
field2 TEXT,
PRIMARY KEY(field1, field2)
);
You cannot create the primary key after the fact using ALTER TABLE.
On the other hand, you can create a UNIQUE INDEX after the fact
which has essentially the same effect as a PRIMARY KEY:
CREATE UNIQUE INDEX pk_index ON "table1"("field1","field2");
I am not sure how you have created, the tables, and if you have added the primary index later, but grab the database to your desktop, and check out how works in a desktop environment.
You can't make combinations like that, but you don't need them. What is stopping you from just having a truly id column ?
Related
I am using SQLite Database for my application. I have 4 columns- Student_Name,Student_Enroll, Student_Mob, Student_Address in my database. Now I can add new record if and only if one of four column value is different or all values are different. If all column values are same then no new record should be generated.
Can you please guide me to solve this issue?
To enforce that a set of columns must be unique, add a UNIQUE constraint:
create table Students (
/* ID INTEGER PRIMARY KEY, */
Student_Name TEXT,
Student_Enroll TEXT,
Student_Mob TEXT,
Student_Address TEXT,
UNIQUE (Student_Name, Student_Enroll, Student_Mob, Student_Address)
);
This allows new rows only if at least one of the four columns has a different value.
With a plain INSERT, attempting to insert a duplicate row will result in an error. If you simply want to ignore it instead, use INSERT OR IGNORE:
INSERT OR IGNORE INTO Students ...;
Despite of set your column as UNIQUE you also need to resolve the conflict created on each column when you try to insert new data.
To do so, define the behavior to solve the conflict:
"CREATE TABLE table (your columns here...(UNIQUE unique colums here...) ON CONFLICT REPLACE);"
During Create Database line insert UNIQUE ...for each column to insert only unique record.
Solution 1: (Simple)
Define all columns as unique:
create table TableName (id integer primary key autoincrement,
Student_Name text not null unique,
Student_Enroll text not null unique,
Student_Mob text not null unique);
You can add Student_Address as well, if you need to
Solution 2: (bit complex)
Use AND Operator with WHERE clause
INSERT INTO TableName (Student_Name, Student_Enroll, Student_Mob)
SELECT varStudentName, varStudentEnroll, varStudentMob
WHERE NOT EXISTS(SELECT 1 FROM TableName WHERE Student_Name = varStudentName OR Student_Enroll = varStudentEnroll OR Student_Mob = varStudentMob );
//If a record already contains a row, then the insert operation will be ignored.
You can find more information at the sqlite manual.
Live Example:
Open SQLite Online
Paste following code:
INSERT INTO demo (id,name,hint)
SELECT 4, 'jQuery', 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML'
WHERE NOT EXISTS(SELECT 1 FROM demo WHERE name = 'jQuery' OR hint = 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML' );
SELECT * from demo
Hit RUN
This won't insert 4th record and if you modify both values of WHERE clause then record will be inserted.
According to some blogs like http://reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ and even in some of the aswers here.
One of the first steps before including the datababe into the project is to rename the primary id field of your tables to "_id" so Android will know where to bind the id field of your tables.
What should be done with a table that have a combined primary key
Assume that i'm creating the relation between the product id and the store id to assign it's price.
CREATE TABLE `Products-Stores` (
`product` INTEGER NOT NULL,
`store` INTEGER NOT NULL,
`price` INTEGER NOT NULL,
PRIMARY KEY(product,store)
);
There is no need to rename any column in your database. SQL allows column aliases like this:
SELECT integer_primary_key AS _id
...
The only time this is necessary is when you are using a ListAdapter to display the contents of a cursor queried from your DB. You must have an integer primary key column, named "_id" in the cursor, to do that
Better yet, every SQLite database table has an implicit column named "rowid". You don't even have to have your own integer primary key column. Just use rowid, like so:
SELECT rowid AS _id
...
EDITED TO INCLUDE #CL's EXPLANATION OF WORKING JOINS
Obviously, this trick won't work, for many kinds of joins. As long as the rowids are unique over all the rows in the join, though, it works fine.
im creating a Table with this command :
create table if not exists Event ( _id long INTEGER AUTO INCREMENT,repeatEvery long ,repeating int ,startTime long ,title text ,primary key (_id) );
also tried id without the _ prefix, and then i fetch all rows with
database.query("Event",null , null, null, null, null, null);
and then i go over the results printing the ID column :
if (c.moveToFirst()) {
do {
System.out.println(c.getLong(c.getColumnIndexOrThrow("_id")));
} while (c.moveToNext());
}
all of the results are zeros! idea any one?
SQLITE by default adds an INTEGER AUTOINCREMENT for you. Search for ROWID. The creation of a column that replicates this functionality will just be created as an alias to ROWID.
I did some more digging around and found out what some of the issues are. First of all, SQLITE is garbage.
Here is the correct SQL statement you need to use.
CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT,repeatEvery long ,repeating int ,startTime long ,title text)
I issued the one in your code sample, and it had the type of the _id column as "INTEGER AUTO INCREMENT". The SQLITE parser is very generous and accepted that as a datatype. It had no idea what to do with it, and just treated it as a blob, and none of the constraints worked. So, even though your DDL was incorrect, SQLITE was nice enough to take it's best guess at what was wrong and didn't bother to let you know. :[
If you print the schema of your apps' Event table, you'll should see the INTEGER AUTO INCREMENT issue.
Another issue to watch out for,
If you're writing your insert statements on your own, you need to write in one of these two ways.
insert into Event (repeatEvery, repeating, startTime, title) values (1,2,3, "title");
or
insert into Event values (NULL, 1,2,3, "title");
the SQLITE Helper class should handle this for you.
From the sqlite docs it looks like the definition should be changed a little.
the definition should probably be:
create table if not exists Event ( _id INTEGER PRIMARY KEY, repeatEvery long, repeating int, startTime long, title text );
Simply :
create table if not exists Event ( _id INTEGER PRIMARY KEY,repeatEvery long ,repeating int ,startTime long ,title text );
for some reason, should not declare column type...
I'm trying to create a table and I've tried so many times to figure this out... for some reason it won't accept this.. it's saying something about the auto_increment
create table if not exists Assignments(
id auto_increment primary key,
class_name VARCHAR(30),
assignment_name VARCHAR(30) not null,
due_date VARCHAR(30) not null,
notes VARCHAR(30));
whats the problem?
EDIT: i am trying to use SQLite eventually but this command was written on my mySQL thru WAMP
First of all, Android uses SQLite, so your mysql tag is slightly incorrect unless I'm missing something you're doing.
Secondly, you would say
CREATE TABLE ASSIGNMENTS(id INTEGER PRIMARY KEY, class_name TEXT, assignment_name TEXT NOT NULL, due_date TEXT NOT NULL, notes TEXT);
"autoincrement" is handled automatically if you set your primary key as an INTEGER type, even though under the covers SQLite uses strings for everything
reference: SQLite datatypes
further reference: INTEGER PRIMARY KEY
Even more reference: "If an INSERT statement attempts to insert a NULL value into a rowid or integer primary key column, the system chooses an integer value to use as the rowid automatically. A detailed description of how this is done is provided separately."
It is autoincrement, not auto_increment
Can anyone tell me how to declare a composite primary key in Android 1.6 which includes an autoincrement _id column? I'm not sure of the syntax. I've ended up just enforcing it in Java when I try to add values (where registrationNumber + date has to be unique in the table):
Cursor fuelUpsCursor = getFuelUps(registrationNumber, date);
if(!fuelUpsCursor.moveToNext())
{
//add registrationNumber and date
}
I don't really need the _id column but it can make life tricky if tables don't have one.
Cheers,
Barry
Your question does not make much sense. Your subject line asks for a "composite foreign key", your first sentence asks for a "composite primary key" with an AUTOINCREMENT that your sample code then ignores.
I am going to interpret your question this way: You want an _ID INTEGER PRIMARY KEY AUTOINCREMENT column in your table to be able to use Android's CursorAdapter, but you want to also make sure that the combination of two other columns is unique.
In that case, I think that you want to use a UNIQUE constraint:
Multiple Unique Columns in SQLite
SQLite table constraint - unique on multiple columns
http://sqlite.org/lang_createtable.html