How do I import data into a table with composite key in SQLite? - sqlite

So I have a table with a composite key defined as follows:
create table BOOK_REVIEW
(
ISBN varchar(13) NOT NULL,
ID_Num int NOT NULL,
Rating int NOT NULL,
Review varchar(8000),
primary key (ISBN, ID_Num),
foreign key (ISBN) references BOOK(ISBN)
ON DELETE cascade ON UPDATE cascade,
foreign key (ID_Num) references CONTACT(ID_Num)
ON DELETE cascade ON UPDATE cascade
);
The problem I'm having is that when I import data from a properly formatted csv file, I get the duplicate entry error. It's true that there are duplicate entries for ISBN, and there are duplicate entries for ID_Num in this table, but the composite key of (ISBN, ID_Num) is unique to each row. Why then am I getting the error?
I can obviously omit the primary key declaration and everything will import just fine, but I need the primary key to be defined correctly.
I've tried importing to a table without the primary key definition, then moving all data to a temp table, dropping the table and recreating with the primary key constraint, then trying to move everything back...but as expected the "duplicate entry" error pops again.
Any idea how to populate a table with a composite key by importing directly from a properly formatted csv file?

Related

I can't add foriegn key to my existing table. | sqlite3

So i am trying to complete finance. Following is the .schema:
sqlite> .schema
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username TEXT NOT NULL, hash TEXT NOT NULL, cash NUMERIC NOT NULL DEFAULT 10000.00);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE history(
symbol TEXT, name TEXT, shares INTEGER, price NUMERIC, time DATETIME
);
CREATE UNIQUE INDEX username ON users (username);
When i try to add foriegn key to history table it always return error. Here is my code:
sqlite> ALTER TABLE history ADD COLUMN id INT;
sqlite> ALTER TABLE history ADD FOREIGN KEY(id) REFRENCES users(id);
Parse error: near "FOREIGN": syntax error
ALTER TABLE history ADD FOREIGN KEY(id) REFRENCES users(id);
^--- error here
I think based on what I see in the sqlite docs that the statement should be together with the ADD column:
ALTER TABLE history ADD COLUMN id INTEGER REFERENCES users(id);
But you please check me on this syntax! Another option is to take care of creating the constraint at the same time that you create the table.
CREATE TABLE history(
symbol TEXT,
name TEXT,
shares INTEGER,
price NUMERIC,
time DATETIME,
id INTEGER,
FOREIGN KEY (id)
REFERENCES users (id));
It might not be something you have realized (yet) but every database has its unique flavor of SQL, so despite there being a SQL standard there are often little differences in the syntax of SQL for specific db implementations. So you always have to beware of this when looking up commands for your sql db.
Further detail on Sqlite foreign key constraints can be found here:
https://www.sqlitetutorial.net/sqlite-foreign-key/

Error on adding PRIMARY KEY to existing table [duplicate]

I keep getting an error "Incorrect index name 'f7'" using MySQL and I've narrowed it down to the following:
First I create the table,
CREATE TABLE testTable (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
f7 INTEGER NOT NULL,
FOREIGN KEY (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB;
And then elsewhere,
ALTER TABLE testTable ADD UNIQUE f7;
This has led me to believe that this has to do with a duplicate index (?) I just can't figure out how to fix it. Many thanks.
Give it a name, so it doesn't conflict with the foreign Key index
ALTER TABLE `testtable` ADD UNIQUE INDEX `foo` (`f7`);
An incorrect index name error is given when you're attempting to create a new index with the same name as an existing index.
In MySQL, when you create a foreign key, as you're doing with FOREIGN KEY (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE, an index is auto-created as well. In this case, the name is defaulted to f7.
The foreign key is created as a non-unique index; your second command: ALTER TABLE testTable ADD UNIQUE (f7); will make this index unique - not add a second one.
To verify what indexes already exist on the table, you can use the following:
SHOW INDEXES FROM testTable;
If you're receiving this error, there is likely additional code elsewhere that is attempting to create an index named f7. You can attempt to find it, or change your CREATE TABLE syntax to name the key something different so that it doesn't cause conflicts:
FOREIGN KEY fk_testTable_f7 (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE
In this example, I used fk_testTable_f7 and you should now have a non-unique index on the table named fk_testTable_f7. To make it unique, you can use your existing ALTER command as you want the column to be unique - not the foreign key itself.

Sqlite FOREIGN KEY constraint failed during add column

My issue is that I am getting a foreign key constraint error when I try to add a column to a table. Not a row, a column!
My table is called Screens. It has two tables with foreign key dependencies. They are called Topic and ScreenTypes. Both tables are very small and they only have 2 columns each (id and name). The Screens table contains the columns TopicId and ScreenTypeId plus a couple of other columns. All three table have primary indexes. Everything has been working fine for the past few weeks.
Then, I tried to add a new column to the Screens table called ScreenNumber. The new column is numeric and has no restrictions whatsoever. But, when I tried to commit the change to the schema, I got a foreign key constraint error.
I thought I would get around it by removing the foreign key constraint, adding the column and then adding the foreign key constraint back. But, when I tried to remove the foreign key constraint, I got another foreign key constraint error.
Any help would be greatly appreciated! I have no idea what is causing this and I am past my deadline for this project.
My table is called Screens. It has two tables with foreign key
dependencies. They are called Topic and ScreenTypes. Both tables are
very small and they only have 2 columns each (id and name). The
Screens table contains the columns TopicId and ScreenTypeId plus a
couple of other columns. All three table have primary indexes.
Everything has been working fine for the past few weeks.
From the above and your comments then this appears to create the Screens Table, the Topics Table and the ScreenTypes table and additionally populate the tables with some data:-
DROP TABLE IF EXISTS Screens;
CREATE TABLE IF NOT EXISTS Screens (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
Video TEXT NOT NULL,
TopicId INTEGER NOT NULL,
Instructions TEXT,
ScreenTypeId INTEGER,
SortOrder INTEGER DEFAULT (10),
Image TEXT,
NewColumn INTEGER,
FOREIGN KEY (TopicId) REFERENCES Topics (id),
FOREIGN KEY (ScreenTypeId) REFERENCES ScreenTypes (id)
)
;
DROP TABLE IF EXISTS Topics;
CREATE TABLE IF NOT EXISTS Topics (ID INTEGER PRIMARY KEY, name TEXT);
DROP TABLE IF EXISTS ScreenTypes;
CREATE TABLE IF NOT EXISTS ScreenTypes (ID INTEGER PRIMARY KEY, name TEXT);
INSERT INTO Topics (name) VALUES ('Topic1'),('Topic2'),('Topic3'),('Topic4');
INSERT INTO ScreenTypes (name) VALUES ('SreenType1'),('ScreenType2'),('ScreenType3'),('ScreenType4');
INSERT INTO Screens (Video,TopicId,Instructions,ScreenTypeId,Image,NewColumn) VALUES
('Video1',2,'do this 001',3,'Image1','blah'),
('Video2',2,'do this 002',3,'Image2','blah'),
('Video3',1,'do this 002',1,'Image3','blah'),
('Video4',3,'do this 004',4,'Image4','blah'),
('Video5',4,'do this 005',1,'Image5','blah')
;
Then, I tried to add a new column to the Screens table called
ScreenNumber. The new column is numeric and has no restrictions
whatsoever. But, when I tried to commit the change to the schema, I
got a foreign key constraint error.
The following works :-
ALTER TABLE Screens ADD COLUMN ScreenNumber INTEGER DEFAULT 100;
as per :-
ALTER TABLE Screens ADD COLUMN ScreenNumber INTEGER DEFAULT 100
OK
Time: 0.083s
and then using the following
SELECT * FROM Screens;
The result is :-
As can be seen, there were no FK constraint conflicts and the column has been added and the default value of 100 applied.
I suspect that your issues with FK Constraints is that you are progressively try to correct issues.
First (at a guess) you try altering (renaming) the Screens table but can't because of the Fk constraint conflicts with the Fields table. You then try altering the Fields table but still you get FK conflicts, due to :-
If an "ALTER TABLE ... RENAME TO" command is used to rename a table that is the parent table of one or more foreign key constraints, the definitions of the foreign key constraints are modified to refer to the parent table by its new name. The text of the child CREATE TABLE statement or statements stored in the sqlite_master table are modified to reflect the new parent table name.
SQLite Foreign Key Support - 5. CREATE, ALTER and DROP TABLE commands
Of course, if acccording to your description, you only want to add the column then the ALTER TABLE Screens ADD COLUMN ScreenNumber INTEGER (with default value if wanted) works without the need to rename tables.

How to get the names of foreign key constraints in SQLite?

Does SQLite indeed have a limitation that it is not possible to retrieve the name of a foreign key? I am asking because I couldn't find this limitation mentioned anywhere in their documentation.
For example, I run the following script:
CREATE TABLE
users (
id INTEGER NOT NULL PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL
) ;
CREATE TABLE
orders (
id INTEGER NOT NULL PRIMARY KEY,
user_id INTEGER NOT NULL,
CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users(id)
) ;
Now I would like to check that the key "fk_users" was created indeed, so I run the following PRAGMA:
PRAGMA foreign_key_list(orders);
I would expect to see the name of my foreign key in the first column, but I am seeing some "0" value instead. Moreover, if I create multiple foreign keys with custom names, they are all called either "0" or "1".
Is this indeed a limitation of SQLite, or am I missing something?
There is no mechanism to extract the constraint name.
The table sqlite_master stores a CREATE command in the column "sql". You could query that command and do some parsing to extract the name of the foreign key. An example for a combined foreign key that works for me:
SELECT sql FROM sqlite_master WHERE name = 'song'
yields
CREATE TABLE "song" (
"songid" INTEGER,
"songartist" TEXT,
"songalbum" TEXT,
"songname" TEXT,
CONSTRAINT "fk__song_album" FOREIGN KEY ("songartist", "songalbum") REFERENCES "album" ("albumartist", "albumname")
)
and contains the name "fk__song_album" of the foreign key.
If one alters the foreign key with a query, the content of the sql column is modified/updated:
The text in the sqlite_master.sql column is a copy of the original CREATE statement text that created the object, except normalized as described above and as modified by subsequent ALTER TABLE statements. The sqlite_master.sql is NULL for the internal indexes that are automatically created by UNIQUE or PRIMARY KEY constraints.
https://www.sqlite.org/fileformat2.html
Extra tip:
In order to see the foreign key information in Navicat (Lite) ... right click on a table and choose "Design table". Then select the foreign keys tab.

SQLlite: strange "Abort due to constraint violation"

I'm trying to rename a column of a table. I have a lot of tables with the word "couleur" and I renamed "manually" to "bulle".
I've successfully renamed main_groupecouleurs to main_groupebulles. Now i'm working on main_groupe. I'm trying to rename groupe_couleurs_id to groupe_bulles_id
The SQL is quite self-explaining:
BEGIN TRANSACTION;
DROP INDEX main_groupe_fc5cee5b;
CREATE TABLE main_groupe7e12
(
id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
exemple TEXT,
groupe_bulles_id INTEGER DEFAULT NULL,
reference TEXT,
FOREIGN KEY (groupe_bulles_id) REFERENCES main_groupebulles(id)
DEFERRABLE INITIALLY DEFERRED
);
CREATE UNIQUE INDEX main_groupe_fc5cee5b ON main_groupe7e12 (groupe_bulles_id);
INSERT INTO main_groupe7e12(id, description, exemple, groupe_bulles_id, reference)
SELECT id, description, exemple, groupe_couleurs_id, reference
FROM main_groupe;
DROP TABLE main_groupe;
ALTER TABLE main_groupe7e12 RENAME TO main_groupe;
COMMIT;
When I run it, I get:
[SQLITE_CONSTRAINT] Abort due to constraint violation
(UNIQUE constraint failed: main_groupe7e12.groupe_bulles_id)
This means (I think I'm wrong here but I dont know what I'm missing) that it tries to insert some groupe_couleurs_id that are not in the referring table (= main_groupebulles). Thus I tried to see in the original table the problem:
SELECT * FROM main_groupe WHERE groupe_couleurs_id NOT IN (
SELECT id FROM main_groupebulles
);
I got no rows! What am I missing?
You have an UNIQUE index on your groupe_bulles_id column but based on the comments, there are a lot of valid duplicate values for that column coming from main_groupe.groupe_couleus_id and that causes the constraint violation.
Since having duplicate values is what you want, remove the UNIQUE from the CREATE UNIQUE INDEX ....

Resources