I am having some trouble getting my foreign keys to match up with some of my primary keys. I keep getting the error "Error: Cannot add foreign key constraint". I don't know what I'm doing wrong but it might be because I have been staring at it for too long. Any suggestions?
//customer table
statement.execute("CREATE TABLE IF NOT EXISTS mydb.Customers ("
+ " FirstName VARCHAR(21) NOT NULL, "
+ " StreetAddress VARCHAR(45) NULL, "
+ " TelephoneNumber VARCHAR(45) NULL, "
+ " SetOfFrequentFlyerMemberships VARCHAR(45) NULL, "
+ " PreferredPaymentMethod VARCHAR(45) NULL, "
+ " Preferences VARCHAR(45) NULL, "
+ " City VARCHAR(45) NULL, "
+ " State INT NULL, "
+ " LastName VARCHAR(45) NULL, "
+ " CustomerID VARCHAR(45) NOT NULL, "
+ " Customerscol VARCHAR(45) NOT NULL, "
+ " PRIMARY KEY (CustomerID, Preferences))");
//reservation table
statement.execute("CREATE TABLE IF NOT EXISTS mydb.Reservations ( "
+ " CustomerID INT NOT NULL, "
+ " TravelAgent VARCHAR(45) NOT NULL, "
+ " FlightID INT NULL, "
+ " PaymentType VARCHAR(45) NULL, "
+ " StatusOfReservation VARCHAR(45) NULL, "
+ " ReservationID VARCHAR(45) NOT NULL, "
+ " PaymentID INT NOT NULL, "
+ " Preferences VARCHAR(45) NULL, "
+ " PRIMARY KEY (ReservationID), "
+ " CONSTRAINT fk_Reservations_Customers1 "
+ " FOREIGN KEY (CustomerID) "
+ " REFERENCES mydb.Customers(CustomerID), "
+ " CONSTRAINT fk_Reservations_Payment1 "
+ " FOREIGN KEY (PaymentID) "
+ " REFERENCES mydb.Payment(PaymentID), "
+ " CONSTRAINT fk_Reservations_Flights1 "
+ " FOREIGN KEY (FlightID) "
+ " REFERENCES mydb.Flights(FlightID), "
+ " CONSTRAINT fk_Reservations_Preference1 "
+ " FOREIGN KEY (Preferences) "
+ " REFERENCES mydb.Customers(Preferences))");
//frequent flyer membership
statement.execute("CREATE TABLE IF NOT EXISTS mydb.FrequentFlyerMemberships ( "
+ " FrequentFlyerID INT NOT NULL, "
+ " customerID VARCHAR(45) NULL, "
+ " ReservationID VARCHAR(45) NULL, "
+ " PRIMARY KEY (FrequentFlyerID), "
+ " CONSTRAINT fk_FrequentFlyerMemberships_Reservations1 "
+ " FOREIGN KEY (ReservationID) "
+ " REFERENCES mydb.Reservations(ReservationID))");
This isn't all of my code but these are the only blocks that I seem to be having problems with.
use like the below script for making foreign key to composite key of other table
This will work
CONSTRAINT fk_Reservations_Customers1
FOREIGN KEY (CustomerID,Preferences)
REFERENCES stackoverflowprob.Customers(CustomerID,Preferences));
Related
I am trying to create 2 tables: Person and Friend.
In the Friends table, I have a composite primary foreign key that references personId from the Person Table.
Please note i'm trying to do this in Java (Eclipse IDE).
I keep getting this error when I'm trying to create the Friends table for some reason:
ORA-00904: : invalid identifier
String createPersonalInformationTable =
"CREATE TABLE Persons("
+ "personId INT NOT NULL, "
+ "email_userName VARCHAR2(50) NOT NULL, "
+ "password VARCHAR2(50) NOT NULL, "
+ "firstName VARCHAR2(50) NOT NULL, "
+ "midlleName VARCHAR2(50), "
+ "lastName VARCHAR2(50) NOT NULL, "
+ "country VARCHAR2(50) NOT NULL, "
+ "city VARCHAR2(50) NOT NULL, "
+ "PRIMARY KEY (personId), "
+ "UNIQUE (email_userName)"
+ ")";
String createFriendsTable =
"CREATE TABLE Friends("
+ "personId INT NOT NULL, "
+ "friendId INT NOT NULL, "
+ "status VARCHAR2(50) NOT NULL, "
+ "PRIMARY KEY (personId, friendId), "
+ "FOREIGN KEY (personId) REFERENCES Persons(personId), "
+ "FOREIGN KEY (friendId) REFERENCES Persons(personId), "
+ ")";
String createFriendsTable =
"CREATE TABLE Friends("
+ "personId INT NOT NULL, "
+ "friendId INT NOT NULL, "
+ "status VARCHAR2(50) NOT NULL, "
+ "PRIMARY KEY (personId, friendId), "
+ "FOREIGN KEY (personId) REFERENCES Persons(personId), "
+ "FOREIGN KEY (friendId) REFERENCES Persons(personId), "
^
+ ")";
Extra trailing comma
I have 3 tables
Table 1 : Member - To store every information about the member,
Attribute : MemberUsername(PK), MemberPassword
Table 2 : MsGroup - To store every registered group
Attribute : GroupId(PK), GroupName, GroupDescription
Table 3 : MsGroupDetail - To store list of every username in every group
Attribute : GroupId(PK,FK), MemberUsername(PK,FK)
My Query for Creating that 3 tables :
db.execSQL("CREATE TABLE IF NOT EXISTS " + MS_MEMBER + " ("
+ MEMBER_USERNAME + " TEXT PRIMARY KEY NOT NULL, "
+ MEMBER_PASSWORD + " TEXT NOT NULL, " + MEMBER_EMAIL
+ " TEXT NOT NULL" + ");");
db.execSQL("CREATE TABLE IF NOT EXISTS " + MS_GROUP + " ("
+ GROUP_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ GROUP_NAME + " TEXT NOT NULL, " + GROUP_DESCRIPTION
+ " TEXT NOT NULL);");
db.execSQL("CREATE TABLE IF NOT EXISTS " + MS_GROUP_DETAIL + " ("
+ GROUP_ID + " INTEGER PRIMARY KEY, " + MEMBER_USERNAME
+ " TEXT, FOREIGN KEY (" + MEMBER_USERNAME
+ ") REFERENCES " + MS_MEMBER + "(" + MEMBER_USERNAME
+ "), FOREIGN KEY (" + GROUP_ID + ") REFERENCES "
+ MS_GROUP + "(" + GROUP_ID + "));");
I have successfully make some code to create member, create group, but the problem is I failed to create a query to invite/add a new member to a group (Failed to insert to MsGroupDetail)
This is the syntax for adding GroupMember
public void addGroupMember(String groupId, String username) {
// TODO Auto-generated method stub
ContentValues cv2 = new ContentValues();
cv2.put(GROUP_ID, groupId);
cv2.put(MEMBER_USERNAME, username);
ourDatabase.insert(MS_GROUP_DETAIL, null, cv2);
}
And this is the syntax to see the list of my Groups
public String[] fetchGroupName(String username) {
int i = 0;
String Query = "SELECT " + GROUP_NAME + " From " + MS_GROUP
+ " a INNER JOIN " + MS_GROUP_DETAIL + " b ON a." + GROUP_ID
+ "=b." + GROUP_ID + " WHERE " + MEMBER_USERNAME + "=?";
Cursor c = ourDatabase.rawQuery(Query, new String[] { username });
String groupName[] = new String[c.getCount()];
int iGroupName = c.getColumnIndex(GROUP_NAME);
c.moveToFirst();
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
groupName[i] = c.getString(iGroupName);
i++;
}
c.close();
return groupName;
}
Everytime I invite a new member/adding to MsGroupDetail table, I failed to insert it to MsGroupDetail and the log cat said : "SQLite Constraint Exception, primary key must be unique"
*nb : My MsGroupDetail is once again to list every member within a group,
I have tested the same concept in Sql Server Management Studio 2008 and It worked, aI dont know any better concept than what I've coded above,
Can you guys please tell me is there any solution for this?
Thank you so much..
The problem is your GROUP_ID is not unique. If you have two members in group 1, your table will have two entries --
1, Member 1
1, Member 2
By specifying "PRIMARY KEY" on GROUP_ID you are stating it will be unique. You need different primary key. In android, it is common to use "_id", something like --
db.execSQL("CREATE TABLE IF NOT EXISTS " + MS_GROUP_DETAIL + " ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ GROUP_ID + " INTEGER, " + MEMBER_USERNAME
+ " TEXT, FOREIGN KEY (" + MEMBER_USERNAME
+ ") REFERENCES " + MS_MEMBER + "(" + MEMBER_USERNAME
+ "), FOREIGN KEY (" + GROUP_ID + ") REFERENCES "
+ MS_GROUP + "(" + GROUP_ID + "));");
I have probed numerous questions and documentation on this error and cannot seem to find where I am going wrong. The error is on this line:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot add or update a child row: a foreign key constraint fails (`flutweets`.`refs`,
CONSTRAINT `refs_ibfk_1` FOREIGN KEY (`id`) REFERENCES `tweets` (`id`))
The database is MySQL, and I am using Workbench to inspect it; I also know that all the database engines are InnoDB and the Row Formats are Compact. I have three tables: tweets, hashtags, and references.
Here is where I create the tables:
tweets Table
Statement stmt = null;
try {
stmt = connection.createStatement();
stmt.executeUpdate("CREATE TABLE " + TWEETS_TABLE + "("
+ TWEETS_ID + " BIGINT NOT NULL AUTO_INCREMENT,"
+ TWEETS_TIME + " VARCHAR(255),"
+ TWEETS_USER + " VARCHAR(255),"
+ TWEETS_TEXT + " VARCHAR(255) NOT NULL,"
+ TWEETS_LOCATION + " VARCHAR(255),"
+ TWEETS_CITY + " VARCHAR(255),"
+ TWEETS_PROVINCE + " VARCHAR(255),"
+ TWEETS_COUNTRY + " VARCHAR(255),"
+ TWEETS_TIME_ZONE + " VARCHAR(255),"
+ TWEETS_LATITUDE + " DECIMAL(20,16),"
+ TWEETS_LONGITUDE + " DECIMAL(20,16),"
+ "PRIMARY KEY (" + TWEETS_ID + ")"
+ ")");
. . .
hashtags Table
Statement stmt = null;
try {
stmt = connection.createStatement();
stmt.executeUpdate("CREATE TABLE " + HASHTAG_TABLE + "("
+ HASHTAG_ID + " BIGINT NOT NULL AUTO_INCREMENT,"
+ HASHTAG_TEXT + " VARCHAR(255),"
+ TWEETS_ID + " BIGINT NOT NULL,"
+ "PRIMARY KEY (" + HASHTAG_ID + "),"
+ "FOREIGN KEY (" + TWEETS_ID + ")"
+ "REFERENCES " + TWEETS_TABLE
+ "(" + TWEETS_ID + ")"
+ ")");
. . .
references Table
Statement stmt = null;
try {
stmt = connection.createStatement();
stmt.executeUpdate("CREATE TABLE " + REF_TABLE + "("
+ REF_ID + " BIGINT NOT NULL AUTO_INCREMENT,"
+ REF_TEXT + " VARCHAR(255),"
+ TWEETS_ID + " BIGINT NOT NULL,"
+ "PRIMARY KEY (" + REF_ID + "),"
+ "FOREIGN KEY (" + TWEETS_ID + ")"
+ "REFERENCES " + TWEETS_TABLE
+ "(" + TWEETS_ID + ")"
+ ")");
Here are the statements I use to insert and the methods to insert them (I am using prepared statements):
/* INITIALIZE PREPARED STATEMENTS */
// Tweets
private static final String TWEETS_INSERT = "INSERT INTO " + TWEETS_TABLE
+ " (" + TWEETS_TIME + ", " + TWEETS_USER + ", " + TWEETS_TEXT + ", " + TWEETS_LOCATION + ", " + TWEETS_CITY + ", " + TWEETS_PROVINCE + ", "
+ TWEETS_COUNTRY + ", " + TWEETS_TIME_ZONE + ", " + TWEETS_LATITUDE + ", " + TWEETS_LONGITUDE + ")"
+ " VALUES(?,?,?,?,?,?,?,?,?,?)";
private PreparedStatement tweetsStatement;
// Hashtags
private static final String HASHTAGS_INSERT = "INSERT INTO " + HASHTAG_TABLE
+ " (" + HASHTAG_TEXT + ", " + TWEETS_ID + ")" + " VALUES(?,?)";
private PreparedStatement hashStatement;
// References
private static final String REF_INSERT = "INSERT INTO " + REF_TABLE
+ " (" + REF_TEXT + ", " + TWEETS_ID + ")" + " VALUES(?,?)";
private PreparedStatement refStatement;
public void insertHashtag(FluTweet tweet, int hashIndex, Integer tweetID) {
// Pull all of the Hashtag's relevant elements.
String hashText = tweet.getHashtag(hashIndex);
try {
hashStatement.setString(1, hashText);
hashStatement.setString(2, tweetID.toString());
//INSERT HASHTAG INTO TABLE
hashStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void insertReference(FluTweet tweet, int referenceIndex, Integer tweetID) {
// Pull all of the Reference's relevant elements.
String refText = tweet.getReference(referenceIndex);
try {
refStatement.setString(1, refText);
refStatement.setString(2, tweetID.toString());
//INSERT REFERENCE INTO TABLE
refStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
I have no idea why this is not working, any help would be much appreciated. Like I said, I have probed numerous other posts and cannot find relevant help.
Background
I found out the answer to my own question. It was never a problem with any of the actual database handling. It turns out, when I was passing the id to be used as the foreign id in hashtags and references, I was getting my id from a counter in the main class; where every new tweet had a number that went with each hashtag and reference for that tweet that would later be used as a foreign key. That foreign key would reference the primary key in the tweets table, which auto increments.
Here was the problem:
It turns out that MySQL is NOT zero-indexed when you auto-increment; where the first value is zero, then one, then two, etc. Instead, it starts at one. So when I tried to reference the primary key with the foreign key, the counter that started at zero for every tweet that I assigned (the foreign key) was being incorrectly matched to the auto incrementing tweet id in the tweets table (primary key).
Therefore, I was always off by one.
I hope this helps anyone that may have a similar issue.
if we didn't set valid child class object primary key value then we can see the MySQLIntegrityConstraintViolationException.if we ignore the primary key value of child class object then based on the configurations set in hibernate pojo/hbm.xml files first level cache(session) will flush it into data base.
I am getting this below exception-
java.sql.SQLException: ORA-00904: : invalid identifier
ORA-06512: at line 1
Below is the query that I am trying to execute-
public static final String DATABASE_TABLE = "LnPData";
public static final String CREATE_SQL = "DECLARE " +
"t_count INTEGER; " +
"v_sql VARCHAR2(1000) := 'create table " +DATABASE_TABLE + "(" +
"(ID number(10,0), " +
"CGUID VARCHAR(255), " +
"PGUID VARCHAR(255), " +
"SGUID VARCHAR(255), " +
"USERID VARCHAR(255), " +
"ULOC VARCHAR(255), " +
"SLOC VARCHAR(255), " +
"PLOC VARCHAR(255), " +
"ALOC VARCHAR(255), " +
"SITEID VARCHAR(255), " +
"PRIMARY KEY ( ID ))'; " +
"BEGIN " +
"SELECT COUNT(*) " +
"INTO t_count " +
"FROM user_tables " +
"WHERE table_name = '" +DATABASE_TABLE + "'; " +
"IF t_count = 0 THEN " +
"EXECUTE IMMEDIATE v_sql; " +
"END IF; " +
"END; ";
On the console it is getting printed as-
DECLARE t_count INTEGER; v_sql VARCHAR2(1000) := 'create table LnPData((ID number(10,0), CGUID VARCHAR(255), PGUID VARCHAR(255), SGUID VARCHAR(255), USERID VARCHAR(255), ULOC VARCHAR(255), SLOC VARCHAR(255), PLOC VARCHAR(255), ALOC VARCHAR(255), SITEID VARCHAR(255), PRIMARY KEY ( ID ))'; BEGIN SELECT COUNT(*) INTO t_count FROM user_tables WHERE table_name = 'LnPData'; IF t_count = 0 THEN EXECUTE IMMEDIATE v_sql; END IF; END;
Change
"v_sql VARCHAR2(1000) := 'create table " +DATABASE_TABLE + "(" +
"(ID number(10,0), " +
into
"v_sql VARCHAR2(1000) := 'create table " +DATABASE_TABLE +
"(ID number(10,0), " +
and it is working. You just had one incorrect bracket.
Im unsure of my problem. I am getting no such table when queriyng the second table.. these are both within the onCreate method
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" + KEY_CBID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_NAME
+ " TEXT NOT NULL, " + KEY_RACE + " TEXT NOT NULL,"
+ KEY_CLASS + " TEXT NOT NULL," + KEY_DEITY
+ " TEXT NOT NULL," + KEY_GENDER + " TEXT NOT NULL,"
+ KEY_HEIGHT + " TEXT NOT NULL," + KEY_WEIGHT
+ " TEXT NOT NULL);");
db.execSQL("CREATE TABLE " + DATABASE_TABLE2 + " (" + KEY_CSID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_SKILL
+ " TEXT NOT NULL, " + KEY_CBID + " INTEGER PRIMARY KEY FOREIGN KEY);"
);
Edit: showing cvs
String skill = "blah test";
Cursor c = ourDatabase.rawQuery("SELECT " + KEY_CBID + " FROM " + DATABASE_TABLE + " order by " + KEY_CBID + " DESC limit 1", null);
if (c != null)
{
c.moveToFirst();
cbid = c.getInt(0);
}
ContentValues cv = new ContentValues();
cv.put(KEY_SKILL, skill);
cv.put(KEY_CBID, cbid);
return ourDatabase.insert(DATABASE_TABLE2, null, cv);
My select statements is:
Cursor c = ourDatabase.rawQuery("SELECT " + KEY_SKILL + ", " + KEY_NAME + ", " + KEY_CBID + " FROM " + DATABASE_TABLE + ", " + DATABASE_TABLE2 + " WHERE " + DATABASE_TABLE +"."+KEY_CBID+" = " +DATABASE_TABLE2+"."+KEY_CBID+" && " +DATABASE_TABLE+"."+KEY_NAME+" = '"+item+"'", null);
I don't believe that your second table is being created, here is how to declare a table with a foreign key:
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER,
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
I took these from SQLite.org.
Also foreign keys are disabled by default in SQLite, for Android use:
db.execSQL("PRAGMA FOREIGN_KEYS=ON;");
before inserting data, if you haven't already;
check you log cat to see if there is an error while creating the second table.
If there is an error from sqllite, it will be logged in logcat
When a new table is added to DB, make sure DB is upgraded
IF from your code if you are calling db.open , if the database is already created it will be open. So in this case the code to create new table will not be hit. So you have to make sure that you upgrade the database where you can delete all your existing tables and create again
#Override
public void onCreate(SQLiteDatabase db) {
createAllTables(db);
Log.v(DBTAG, "DATABASE CREATED");
// Toast.makeText(mCtx, "created", Toast.LENGTH_SHORT).show();
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(DBTAG, "Upgrading database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data");
dropExistingTables(db);
onCreate(db);
}
private void dropExistingTables(SQLiteDatabase db) {
for (int i = 0; i < Utils.getDropTableQueries().size(); i++) {
db.execSQL(Utils.getDropTableQueries().get(i));
}
}
Thus to conclude make sure you are creating the table, and that no error while creating.