sqlite column constraints both unique and foreign - sqlite

Does sqlite allow a column to be both unique and a foreign key at the same time?
How does the definition look like?
CREATE TABLE table1 (
id INTEGER PRIMARY KEY,
fkey INTEGER NOT NULL UNIQUE REFERENCES table2(id)
)
CREATE TABLE table2 (
id INTEGER PRIMARY KEY
)

Sure
CREATE TABLE table1 (
id INTEGER PRIMARY KEY,
fkey INTEGER NOT NULL UNIQUE,
FOREIGN KEY(fkey) REFERENCES table2(id)
)
result.
Query executed successfully: CREATE TABLE table1 (
id INTEGER PRIMARY KEY,
fkey INTEGER NOT NULL UNIQUE,
FOREIGN KEY(fkey) REFERENCES table2(id)
) (took 0ms)
REMEMBER. As of version 3.6.19, SQLite supports foreign key constraints. But enforcement of foreign key constraints is turned off by default (for backwards compatibility). To enable foreign key constraint enforcement, run PRAGMA foreign_keys=ON, from http://sqlite.org/faq.html

Related

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.

Can not add a second foreign key when creating table

I am creating a table with 2 foreign keys
but whenever I have the second key, it will return an error:
CREATE TABLE reviews(
id INTEGER PRIMARY KEY,
stars INT,
business_id INT,
FOREIGN KEY(business_id) REFERENCES businesses(id),
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id)
);
It will throw syntax error near user_id, and if I put business_id after user_id, it will throw syntax error near business_id...
And if I only put one foreign key there, it will just create the table, tried several times. What's the problem here?
users and businesses are two tables, I'm creating a junction table for them.
Don't mix column definition with constraint definition. Columns first, constraints after:
CREATE TABLE reviews(
id INTEGER PRIMARY KEY,
stars INT,
business_id INT,
user_id INT,
FOREIGN KEY(business_id) REFERENCES businesses(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);

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.

foreign key mismatch on delete command for unrelated record

I have the following 5 tables defined with a few records inserted into the 1st 4. This is using sqlite 3.7.1.7 with foreign key constaint enabled.
create table if not exists subject (id varchar(50) primary key,desc varchar(100));
insert into subject (id,desc) values ("subject1","test subject");
create table if not exists subjectlevel (id_subject_id varchar(50) references subject(id) on delete cascade, id integer not null, desc varchar(100) not null, questmcmaxselections integer not null, primary key (id_subject_id,id));
insert into subjectlevel (id_subject_id,id,desc,questmcmaxselections) values ("subject1",1,"test subject1 level 1",4);
insert into subjectlevel (id_subject_id,id,desc,questmcmaxselections) values ("subject1",2,"test subject1 level 2",4);
create table if not exists questmc (id integer primary key, text varchar(300) not null, includeallanswers int not null, subject_id varchar(50), subjectlevel_id integer, foreign key (subject_id, subjectlevel_id) references subjectlevel (id_subject_id,id) on delete cascade);
insert into questmc (text,includeallanswers,subject_id,subjectlevel_id) values ("this is a _ question", 1, "subject1",1);
create table if not exists questmcselection (id integer primary key, text varchar(100) not null, subject_id varchar(50), subjectlevel_id integer, foreign key (subject_id, subjectlevel_id) references subjectlevel (id_subject_id,id) on delete cascade);
insert into questmcselection (text,subject_id,subjectlevel_id) values ("this is a solution","subject1",1);
create table if not exists questmc_questmcselection(id integer primary key, answer integer not null, questmc_id integer, questmcselection_id integer, subject_id varchar(50), subjectlevel_id integer, foreign key (questmc_id) references questmc(id) on delete cascade, foreign key (questmcselection_id) references questmcselection (id) on delete cascade, foreign key (subject_id,subjectlevel_id) references questmc (subject_id,subjectlevel_id) on delete cascade, foreign key (subject_id,subjectlevel_id) references questmcselection (subject_id,subjectlevel_id));
if i attempt to delete the second record in the subjectlevel table, i get a foreign key mismatch error as long as table questmc_questmcselection is defined.
sqlite> delete from subjectlevel where id=2;
Error: foreign key mismatch - "questmc_questmcselection" referencing "questmcselection"
questmc, questmcselection, and questmc_questmcselection have no related existing records that should prevent this deletion. Any idea why this error occurs?
This error has nothing to do with this particular subjectlevel record.
Your problem is that your tables lack the required indexes.
This was not reported earlier because that DELETE statement was the first command that required SQLite to check the consistency of the database schema.
Based on CL's answer -
sqlite> create table parent(a);
sqlite> create table child(a, FOREIGN KEY (a) REFERENCES parent(a));
sqlite> pragma foreign_keys = ON;
sqlite> insert into parent values(3);
sqlite> insert into child values (3);
Error: foreign key mismatch - "child" referencing "parent"
sqlite> create unique index p_a on parent(a);
sqlite> insert into child values (3);
sqlite> _
From the documentation:
Usually, the parent key of a foreign key constraint is the primary key
of the parent table. If [not], then the parent key columns must be
collectively subject to a UNIQUE constraint or have a UNIQUE index [which uses]
the collation sequences ... in the CREATE TABLE
statement for the parent table.
i.e. the alternative is:
sqlite> create table parent(a, b, UNIQUE (a, b));
sqlite> create table child (x, y, FOREIGN KEY (x, y) REFERENCES parent(a, b));
(this also highlights multi-column foreign keys; they work with indexes too...)

SQLite foreign key mismatch error

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.

Resources