I have a table:
CREATE TABLE IF NOT EXISTS city_recent
(_id INTEGER PRIMARY KEY AUTOINCREMENT,
city_id INTEGER NOT NULL,
language BOOL NOT NULL,
type BOOL NOT NULL,
FOREIGN KEY (city_id) REFERENCES city(_id),
UNIQUE(city_id, type) ON CONFLICT IGNORE)
But unique don't work:
I have tested your code and it works as expected (test shown below). Most likely what has happened is that the table was created beforehand without the UNIQUE constraint. Try removing IF NOT EXISTS to confirm.
>>> import sqlite3
>>> con = sqlite3.connect(':memory:')
>>> con.execute('''CREATE TABLE IF NOT EXISTS city_recent
... (_id INTEGER PRIMARY KEY AUTOINCREMENT,
... city_id INTEGER NOT NULL,
... language BOOL NOT NULL,
... type BOOL NOT NULL,
... FOREIGN KEY (city_id) REFERENCES city(_id),
... UNIQUE(city_id, type) ON CONFLICT IGNORE);''')
<sqlite3.Cursor object at 0x01298FA0>
>>> con.execute('insert into city_recent(city_id,language,type) values (0,0,1);')
<sqlite3.Cursor object at 0x0129F120>
>>> con.execute('insert into city_recent(city_id,language,type) values (0,0,1);')
<sqlite3.Cursor object at 0x01298FA0>
>>> con.execute('select * from city_recent').fetchall()
[(1, 0, 0, 1)] # -> note that there is only one row in the table
Related
I have a simple SQLite database created using sqlite3.exe (code is below). When I run it through SchemaSpy, it looks like there are no primary keys in my first three tables. I don't understand what is wrong with the CREATE TABLE statements in the first three tables.
Code In:
.open test1.db
PRAGMA foreign_keys = ON;
CREATE TABLE META_E (E_ID INTEGER PRIMARY KEY NOT NULL, E_Name TEXT, Region TEXT, Date DATE);
CREATE TABLE META_D (D_ID INTEGER PRIMARY KEY NOT NULL, Citation TEXT, is_used BOOLEAN);
CREATE TABLE META_G (Completion TEXT, D_ID INTEGER NOT NULL, Location TEXT, PRIMARY KEY (D_ID), FOREIGN KEY (D_ID) REFERENCES META_D (D_ID));
CREATE TABLE P_ID_Main (Source_File TEXT, P_ID INTEGER NOT NULL, E_ID INTEGER NOT NULL, D_ID INTEGER NOT NULL, PRIMARY KEY (P_ID, E_ID, D_ID), FOREIGN KEY (E_ID) REFERENCES META_E (E_ID), FOREIGN KEY (D_ID) REFERENCES META_D (D_ID));
.dump
Dump:
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE META_E (E_ID INTEGER PRIMARY KEY NOT NULL, E_Name TEXT, Region TEXT, Date DATE);
CREATE TABLE META_D (D_ID INTEGER PRIMARY KEY NOT NULL, Citation TEXT, is_used BOOLEAN);
CREATE TABLE META_G (Completion TEXT, D_ID INTEGER NOT NULL, Location TEXT, PRIMARY KEY (D_ID), FOREIGN KEY (D_ID) REFERENCES META_D (D_ID));
CREATE TABLE P_ID_Main (Source_File TEXT, P_ID INTEGER NOT NULL, E_ID INTEGER NOT NULL, D_ID INTEGER NOT NULL, PRIMARY KEY (P_ID, E_ID, D_ID), FOREIGN KEY (E_ID) REFERENCES META_E (E_ID), FOREIGN KEY (D_ID) REFERENCES META_D (D_ID));
COMMIT;
sqlite>
SchemaSpy:
I don't understand what is wrong with the CREATE TABLE statements in
the first three tables.
I regard to the indexes there is nothing wrong with the CREATE TABLE statements. Rather it appears to be a shortfall of SchemaSpy.
SQLite isn't creating indexes as there is no need as the columns E_ID, D_ID (for both the META_D and META_G tables) are aliases of the rowid column, which could be considered as the MASTER index (see link below).
In short the column's are in fact indexed but there is no need for SQLite to create an index as the index is built in (an exception is a special type of table a WITHOUT ROWID table).
As such the indexes won't appear in sqlite_master, as there is no need and it appears that SchemaSpy at least the way you have it configured, doesn't fully cater for SQLite.
You may wish to refere to ROWIDs and the INTEGER PRIMARY KEY
I need to copy one table to another and both tables contain column with AUTOINCREMENT. Is it possible to insert a defined value into AUTOINCREMENT column.
Tables:
CREATE TABLE tmptimetables (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
_title NVARCHAR(256) NOT NULL,
_weeks INTEGER NOT NULL,
_first_week_date INTEGER NOT NULL,
_auto_complete INTEGER NOT NULL,
_first_lesson_time INTEGER NOT NULL,
_lesson_duration INTEGER NOT NULL,
_break_duration INTEGER NOT NULL,
_color INTEGER NOT NULL,
_symbol NCHAR(1) NOT NULL
);
CREATE TABLE timetables (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title NVARCHAR(256) NOT NULL,
weeks INTEGER NOT NULL,
first_week_date INTEGER NOT NULL,
auto_complete INTEGER NOT NULL,
first_lesson_time INTEGER NOT NULL,
lesson_duration INTEGER NOT NULL,
break_duration INTEGER NOT NULL,
color INTEGER NOT NULL,
symbol NCHAR(1) NOT NULL
);
My SQL request:
INSERT INTO timetables (
auto_complete,
break_duration,
color,
first_lesson_time,
first_week_date, id,
lesson_duration,
symbol,
title,
weeks
)
SELECT
_auto_complete,
_break_duration,
_color,
_first_lesson_time,
_first_week_date,
_id,
_lesson_duration,
_symbol,
_title,
_weeks
FROM tmptimetables
AUTOINCREMENT can only be used for a column that is INTEGER PRIMARY KEY, it is INTEGER PRIMARY KEY that is the factor that makes the column a special column whereby if the value is not provided when inserting a row that a unique integer will be assigned.
So be the column INTEGER PRIMARY KEY or INTEGER PRIMARY KEY AUTOINCREMENT you can specify an integer value and a row may be inserted with the given value.
A row will not be inserted with a given value if that value is not unique.
For example if the table timetables is currently :-
Then
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (null,'mytitle',78,86000,23,1800,900,200,16,'E');
Would insert a new row with the id as determined by SQLite's algorithm for providing a unique id (probably 5).
If the id were changed to be provided (i.e. not null) say to 10 as per :-
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (10,'mytitle',78,86000,23,1800,900,200,16,'E');
Then the id for the new row would be 10.
However if then using (the same SQL but with the last column value changed) :-
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (10,'mytitle',78,86000,23,1800,900,200,16,'Z');
A new row would not be inserted as a row with an id of 10 already exists.
Finally if the id is not given (null is used) but the SQL is otherwise the same a new row is inserted with a unique id being provided by SQLite e.g.
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (null,'mytitle',78,86000,23,1800,900,200,16,'Z');
So the end result of following the above is :-
AUTOINCREMENT
The AUTOINCREMENT keyword, only usable for an INTEGER PRIMARY COLUMN, invokes a different algorithm for determining the next sequence to ensure that the next sequence/id is always greater, whilst without AUTOINCREMENT a lower sequence/id can be applied.
The AUTOINCREMENT keyword does not specify that if a value for the column is not provided then a sequence/id is applied it is INTEGER PRIMARY KEY that specifies that. Well actually, by default, i.e. unless WITHOUT ROWID is specified, this happens for all tables. It's just the the special rowid column is hidden. Specifying <column_name> INTEGER PRIMARY KEY (where is a valid column name) creates an alias of the rowid.
For example using SELECT rowid,* FROM timetables produces :-
SQLite Autoincrement
Rowid Tables
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...)
I have two tables, theme and quiz, here is their definition:
CREATE TABLE "theme" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "nom" VARCHAR NOT NULL );
CREATE TABLE quiz(
id INTEGER PRIMARY KEY,
nom VARCHAR(256) NOT NULL,
theme INTEGER NOT NULL,
niveau INTEGER NOT NULL,
pass INTEGER DEFAULT 1 NOT NULL,
jok INTEGER DEFAULT 1 NOT NULL,
etat INTEGER DEFAULT 0 NOT NULL,
FOREIGN KEY (theme) REFERENCES theme(id)
);
The field id (the primary key) in the table theme is a Foreign Key in the quiz table.
When i try to insert a record in the table quiz which contain the value 30 for example as a foreign key, the record is inserted successfully in the quiz table although there is no record in the theme table with the id = 30, i mean, wasn't supposed to interdict this insert since i had a Foreign key constraint?
Are you sure foreign key support is enabled?
Assuming the library is compiled with foreign key constraints enabled,
it must still be enabled by the application at runtime, using the
PRAGMA foreign_keys command. For example:
sqlite> PRAGMA foreign_keys = ON;
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.