SQLite foreign key mismatch error - sqlite

Why am I getting a SQLite "foreign key mismatch" error when executing script below?
DELETE
FROM rlsconfig
WHERE importer_config_id=2 and
program_mode_config_id=1
Here is main table definition:
CREATE TABLE [RLSConfig] (
"rlsconfig_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"importer_config_id" integer NOT NULL,
"program_mode_config_id" integer NOT NULL,
"l2_channel_config_id" integer NOT NULL,
"rls_fixed_width" integer NOT NULL
,
FOREIGN KEY ([importer_config_id])
REFERENCES [ImporterConfig]([importer_config_id]),
FOREIGN KEY ([program_mode_config_id])
REFERENCES [ImporterConfig]([importer_config_id]),
FOREIGN KEY ([importer_config_id])
REFERENCES [ImporterConfig]([program_mode_config_id]),
FOREIGN KEY ([program_mode_config_id])
REFERENCES [ImporterConfig]([program_mode_config_id])
)
and referenced table:
CREATE TABLE [ImporterConfig] (
"importer_config_id" integer NOT NULL,
"program_mode_config_id" integer NOT NULL,
"selected" integer NOT NULL DEFAULT 0,
"combined_config_id" integer NOT NULL,
"description" varchar(50) NOT NULL COLLATE NOCASE,
"date_created" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
PRIMARY KEY ([program_mode_config_id], [importer_config_id])
,
FOREIGN KEY ([program_mode_config_id])
REFERENCES [ProgramModeConfig]([program_mode_config_id])
)

When you use a foreign key over a table that has a composite primary key you must use a composite foreign key with all the fields that are in the primary key of the referenced table.
Example:
CREATE TABLE IF NOT EXISTS parents
(
key1 INTEGER NOT NULL,
key2 INTEGER NOT NULL,
not_key INTEGER DEFAULT 0,
PRIMARY KEY ( key1, key2 )
);
CREATE TABLE IF NOT EXISTS childs
(
child_key INTEGER NOT NULL,
parentKey1 INTEGER NOT NULL,
parentKey2 INTEGER NOT NULL,
some_data INTEGER,
PRIMARY KEY ( child_key ),
FOREIGN KEY ( parentKey1, parentKey2 ) REFERENCES parents( key1, key2 )
);

I am not sure about SQLite. But I found this link on google. http://www.sqlite.org/foreignkeys.html.
Some of the reasons can be
The parent table does not exist, or
The parent key columns named in the foreign key constraint do not exist, or
The parent key columns named in the foreign key constraint are not the primary key of the parent table and are not subject to a unique constraint using collating sequence specified in the CREATE TABLE, or
The child table references the primary key of the parent without specifying the primary key columns and the number of primary key columns in the parent do not match the number of child key columns.

Unfortunately, SQLite gives this error all the time without mentioning WHICH foreign key constraint failed. You are left to try to check them one by one, which often doesn't work, and then rebuild the table without the constraints and add them back one by one until you find the problem. SQLite is great in a lot of ways, but this isn't one of them.

Related

Strange org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (foreign key mismatch -

I'm running into org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (foreign key mismatch - ... with a statement, that proceeds without any complaints using the normal SQLite-frontend. This creates the crucial part of my database:
CREATE TABLE IF NOT EXISTS artists (
aid INTEGER PRIMARY KEY AUTOINCREMENT,
aname VARCHAR(200) NOT NULL,
CONSTRAINT one UNIQUE(aname)
);
CREATE TABLE IF NOT EXISTS discs (
did INTEGER PRIMARY KEY AUTOINCREMENT,
testAddCD1 BIGINT(10) NOT NULL,
dtitle VARCHAR(125) NOT NULL,
dreleaseyear YEAR(4) DEFAULT NULL,
dlang VARCHAR(3) DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS tracks (
discs_did INTEGER NOT NULL,
tnumber INT(4) NOT NULL,
ttitle VARCHAR(125) NOT NULL,
tseconds INT(4) NOT NULL,
CONSTRAINT pk PRIMARY KEY(discs_did, tnumber),
CONSTRAINT fk FOREIGN KEY(discs_did) REFERENCES discs(did) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT val CHECK(tseconds> 0)
);
CREATE TABLE IF NOT EXISTS track_by_artist (
discs_did INTEGER NOT NULL,
tracks_tnumber INT(4) NOT NULL,
artists_aid INTEGER NOT NULL,
CONSTRAINT pk PRIMARY KEY(discs_did, tracks_tnumber, artists_aid),
CONSTRAINT fk1 FOREIGN KEY(discs_did) REFERENCES discs(did) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT fk2 FOREIGN KEY(tracks_tnumber) REFERENCES tracks(tnumber) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT fk3 FOREIGN KEY(artists_aid) REFERENCES artists(aid) ON DELETE RESTRICT ON UPDATE RESTRICT
The database gets created and the JDBC-driver inserts an artist, a disc and the disc's tracks - all good. The final insert should assign an artist to a track and looks like
INSERT INTO track_by_artist (discs_did, tracks_tnumber, artists_aid) VALUES (1, 1, 1);
Using the JDBC this yields
SQLite-Error #1
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (foreign key mismatch - "track_by_artist" referencing "tracks")
at org.sqlite.core.DB.newSQLException(DB.java:1012)
at org.sqlite.core.DB.newSQLException(DB.java:1024)
at org.sqlite.core.DB.throwex(DB.java:989)
at org.sqlite.core.NativeDB.prepare_utf8(Native Method)
at org.sqlite.core.NativeDB.prepare(NativeDB.java:134)
at org.sqlite.core.DB.prepare(DB.java:257)
at org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:45)
at org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30)
at org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:25)
at org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:35)
at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:241)
at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:205)
Issuing the same SQL-Insert with SQLite's text-frontend works like cream.
I'm a little lost and don't know what to do about my Java-code.
Some advise, pls?
Chris
The problem is that in track_by_artist you defined this foreign key constraint:
CONSTRAINT fk2 FOREIGN KEY(tracks_tnumber) REFERENCES tracks(tnumber) ON DELETE RESTRICT ON UPDATE RESTRICT
although tnumber in tracks is not UNIQUE (and it shouldn't be).
A foreign key's parent must be defined as UNIQUE.
In tracks the PRIMARY KEY is defined as the combination of discs_did and tnumber, which makes sense, so the combination of these 2 columns is unique.
What you can do is define in track_by_artist a composite foreign key for the columns discs_did and tracks_tnumber that reference discs_did and tnumber of tracks:
CREATE TABLE IF NOT EXISTS track_by_artist (
discs_did INTEGER NOT NULL,
tracks_tnumber INT(4) NOT NULL,
artists_aid INTEGER NOT NULL,
CONSTRAINT pk PRIMARY KEY(discs_did, tracks_tnumber, artists_aid),
CONSTRAINT fk1 FOREIGN KEY(discs_did, tracks_tnumber) REFERENCES tracks(discs_did, tnumber) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT fk2 FOREIGN KEY(artists_aid) REFERENCES artists(aid) ON DELETE RESTRICT ON UPDATE RESTRICT
);
This way you don't need a separate foreign key definition for discs_did.

Sqlite foreign key mismatch?

I've read this question and understood the referenced foreign keys to be unique, but somehow the insertion to table are still throwing foreign key mismatch errors:
CREATE TABLE medication (
med_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
med_name VARCHAR (20) NOT NULL,
dosage VARCHAR (10)
);
CREATE TABLE disease (
dis_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
disease_name VARCHAR (20) NOT NULL
);
CREATE TABLE dis_med (
disease_id int NOT NULL,
medication_id int NOT NULL,
CONSTRAINT PK_dis_med PRIMARY KEY (disease_id, medication_id),
CONSTRAINT FK_dis FOREIGN KEY (disease_id) REFERENCES disease (dis_id),
CONSTRAINT FK_med FOREIGN KEY (medication_id) REFERENCES medication (med_id));
CREATE TABLE user_disease (
user_id REFERENCES user (user_id),
dis_id REFERENCES disease (dis_id),
med_id REFERENCES dis_med(medication_id),
CONSTRAINT PK_dis_user PRIMARY KEY (user_id, dis_id)
);
Through the list in the question I cited:
the parent table (medication, disease) exists.
the parent columns exist
the child table references all of the primary key columns in the parent table
Update1
I was able to insert data and bypass the error by altering the user_disease table by composite foreign key. I'd appreciate it if someone can point out what's the best design here. Many thanks in advance!
CREATE TABLE user_disease (
user_id REFERENCES user (user_id),
dis_id REFERENCES disease (dis_id),
med_id REFERENCES dis_med(medication_id),
CONSTRAINT FK_dis_med FOREIGN KEY REFERENCES dis_med(disease_id, medication_id),
CONSTRAINT PK_dis_user PRIMARY KEY (user_id, dis_id)
);
From SQLite Foreign Key Support/3. Required and Suggested Database Indexes:
Usually, the parent key of a foreign key constraint is the primary key of the parent table.
If they are not the primary key, then the parent key columns must be collectively
subject to a UNIQUE constraint or have a UNIQUE index.
With this:
CREATE TABLE user_disease (
...........................
med_id REFERENCES dis_med(medication_id),
...........................
);
the column med_id of user_disease references the column medication_id of dis_med, which is not the PRIMARY KEY of dis_med and there is no UNIQUE constraint for it. It just references med_id of medication .
Why do you need the column med_id in user_disease?
You have dis_id referencing disease, which may also be used to retrieve from dis_med (all) the row(s) from dis_med for that disease.

SQL Error Regarding Foreign Key Restraint

I am currently getting the following error when trying to add to one of my tables:
Error adding record: FOREIGN KEY constraint failed: (INSERT INTO Stock(StockID,ItemName,MinAmountRequired,AmountInStock,Order? (Yes/No),DataLastUpdated,OrderNumber,SupplierRefrence,PurchaseID`) VALUES (1,",0,0,",",0,0,0);)
Currently, This is how I have my tables set up:
Stock
CREATE TABLE Stock (
StockID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
ItemName TEXT NOT NULL,
MinAmountRequired INTEGER NOT NULL,
AmountInStock INTEGER NOT NULL,
Order? (Yes/No) TEXT NOT NULL,
DataLastUpdated TEXT NOT NULL,
OrderNumber INTEGER NOT NULL UNIQUE,
SupplierReference INTEGER NOT NULL,
PurchaseID INTEGER NOT NULL UNIQUE,
FOREIGN KEY(PurchaseID) REFERENCES Purchase(PurchaseID),
FOREIGN KEY(OrderNumber) REFERENCES Orders(OrderNumber),
FOREIGN KEY(SupplierReference) REFERENCES Supplier(SupplierReference));
Orders
CREATE TABLE Orders (
OrderNumber INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
CustomerReferenceNumber INTEGER NOT NULL UNIQUE,
OrderDate TEXT NOT NULL,
ItemName TEXT NOT NULL UNIQUE);
Suppliers
CREATE TABLE Supplier (
SupplierReference INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
Name TEXT NOT NULL UNIQUE,
Address TEXT NOT NULL UNIQUE,
ContactNumber INTEGER NOT NULL UNIQUE);
Purchases
CREATE TABLE Purchase (
PurchaseID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
Date TEXT NOT NULL,
AmountSpent REAL NOT NULL);
You have defined these foreign keys in table Stock:
FOREIGN KEY(PurchaseID) REFERENCES Purchase(PurchaseID),
FOREIGN KEY(OrderNumber) REFERENCES Orders(OrderNumber),
FOREIGN KEY(SupplierReference) REFERENCES Supplier(SupplierReference)
meaning that the values in columns PurchaseID, OrderNumber, SupplierReference need to reference values in columns of the tables Purchase, Orders and Supplier.
But you want to store 0 to all of these columns which I'm sure that is not the value of any of the referenced columns, since these referenced columns are defined as
PRIMARY KEY AUTOINCREMENT
and so their values are > 0.
Pass valid values that do exist in these 3 tables and the statement will execute succesfully.

SQLite3 syntax error trying to create foreign key

I am trying to create a bunch of tables in sqlite3 and I am getting an error that I can't fix. Something to do with my syntax for sqlite3 for foreign keys but can't figure it out.
CREATE TABLE students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
first_name VARCHAR(64),
last_name VARCHAR(64)
);
CREATE TABLE classes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
class_name VARCHAR(64)
);
CREATE TABLE students_classes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
students_id INTEGER,
classes_id INTEGER,
FOREIGN KEY (students_id) REFERENCES students(id),
FOREIGN KEY (classes_id) REFERENCES classes(id)
);
CREATE TABLE teachers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
classes_id INTEGER,
first_name VARCHAR(64),
last_name VARCHAR(64),
FOREIGN KEY classes_id REFERENCES classes(id)
);
CREATE TABLE grades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
students_id INTEGER,
grade_num INTEGER,
FOREIGN KEY students_id REFERENCES students(id)
);
Error: near "students_id": syntax error
SQLite Docs seem to indicate that column name(s) in FOREIGN Key constraint must be inside parenthesis:
I'm not sure how strictly it's actually enforced. My SQL Fiddle shows that using parenthesis should solve your problem.
Please note that SQL Fiddle for SQLite is emulated, so your result might still vary.

many foreign keys in one table sqlite

I want to use many foreign keys in one table on sqlite.
But it makes just one. how can I do it?
CREATE TABLE STORES(
SId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
SName TEXT NOT NULL
)
CREATE TABLE CITY(
CId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
CName TEXT NOT NULL
)
CREATE TABLE PRODUCTS(
PId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
PName TEXT NOT NULL,
Price REAL NOT NULL
)
CREATE TABLE STORE_CITY(
CId INTEGER REFERENCES CITY(CId) NOT NULL,
SId INTEGER REFERENCES STORES(SId) NOT NULL,
PId INTEGER REFERENCES PRODUCTS(PId)
)
Define the columns first, THEN make them foreign keys.
CREATE TABLE STORE_CITY(
CId INTEGER,
SId INTEGER,
PId INTEGER,
FOREIGN KEY (CId) REFERENCES CITY(CId) NOT NULL,
FOREIGN KEY (SId) REFERENCES STORES(SId) NOT NULL,
FOREIGN KEY (PId) REFERENCES PRODUCTS(PId)
)

Resources