How do I resolve a foreign key mismatch error? - sqlite

I tried inserting values into my 'JobTypes' table but I keep getting a foreign key mismatch error. I think I've made an error with my foreign keys but I can't quite figure out where exactly as I'm quite new at this, can anyone help me out?
This is what I have so far:
CREATE TABLE Projects (
Proj_ID INTEGER,
Proj_name TEXT,
PRIMARY KEY (Proj_ID)
);
CREATE TABLE Employees (
Emp_ID INTEGER,
Proj_ID INTEGER,
Emp_fname TEXT,
PRIMARY KEY(Emp_ID, Proj_ID),
FOREIGN KEY(Proj_ID) REFERENCES Projects(Proj_ID)
);
CREATE TABLE HourRates (
Job_type TEXT,
Hour_rate TEXT,
PRIMARY KEY(Job_type)
);
CREATE TABLE JobTypes (
Emp_ID INTEGER,
Job_type TEXT,
PRIMARY KEY(Emp_ID)
FOREIGN KEY (Emp_ID) REFERENCES Employees(Emp_ID)
FOREIGN KEY (Job_type) REFERENCES HourRates(Job_type)
);

Every FKEY target must be either a primary key or have an explicit unique index defined. Employees(Emp_ID) does not have a unique constraint or index. If this column is unique, you need to add a unique constraint or define a simple PKEY. Otherwise, you will not be able insert any data into the JobTypes table. The error message generated is confusing, and SQLite should at least issue some kind of warning when you create the JobTypes table, but this is not how it works, perhaps, due to the need for backward compatibility. Anyhow, my guess is that your Employees table actually needs to be split into Employees & Employees_Projects (many-to-many) tables.

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/

Data first many to many for EF Core

I have a SQLite DB that I am trying to use with EF Core database first.
It has a table of users, and a table of groups that users can belong to, and it has a mapping table because users can belong to multiple groups.
-- holds users
CREATE TABLE IF NOT EXISTS user (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT,
);
-- holds groups users can belong to
CREATE TABLE IF NOT EXISTS group (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT,
);
-- holds user group membership
CREATE TABLE IF NOT EXISTS map_group_user (
group_id INTEGER,
user_id INTEGER,
UNIQUE (group_id,user_id) ON CONFLICT REPLACE,
FOREIGN KEY(group_id) REFERENCES group(_id) ON DELETE CASCADE,
FOREIGN KEY(user_id) REFERENCES user(_id) ON DELETE CASCADE
);
When I scaffold this up I get a warning from dotnet ef scaffold that it could not identify a primary key for map_group_user and it does not generate a model, and neither the User nor Group model contains any reference to the other (expected).
Try adding an explicit primary key to the map_group_user bridge table:
CREATE TABLE IF NOT EXISTS map_group_user (
group_id INTEGER,
user_id INTEGER,
UNIQUE (group_id,user_id) ON CONFLICT REPLACE,
FOREIGN KEY(group_id) REFERENCES "group"(_id) ON DELETE CASCADE,
FOREIGN KEY(user_id) REFERENCES user(_id) ON DELETE CASCADE,
PRIMARY KEY (group_id, user_id)
);
The logical primary key for the map_group_user table is the combination of group_id and user_id, each combination which should ideally appear only once.
By the way, please avoid naming your tables and columns using reserved SQL keywords, such as group. I don't know if this was giving you an error, but I have placed "group" in double quotes to escape it.

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.

sqlite C api how to figure out what tables have foreign keys?

Using the C API, I don't see a way to determine the foreign key constraints for a named table?
Given this example:
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER,
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
sqlite3_table_column_metadata() will tell you it's a primary key, autoincrement, etc. but how
do I get the foreign key constraints?
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
I want to be able to get a list back for table "track" that there are foreign keys back to table Artist column artistid?
I don't see an api to do this? I need to do this programmaticlly upon opening the database, for purposes of aggregation.
Thanks.
After using PRAGMA foreign_key_list(Valuation);
I got back:
PRAGMA foreign_key_list(Valuation);
0|0|Stock|StockId|Id|NO ACTION|NO ACTION|NONE
I understand I need to split on the vertical bar, but what are the first two columns? 0|0 ?
Please note that (foreign) keys can consist of multiple columns, so it would not make sense to return this as column information.
To get information about a table's foreign keys, use this:
PRAGMA foreign_key_list(table-name);
This pragma returns one row for each foreign key constraint created by a REFERENCES clause in the CREATE TABLE statement of table "table-name".

how many foreign key you can have in sqlite table

i spent last few hours trying to find what is wrong in my code(?)
CREATE TABLE transaction (
id NUMERIC PRIMARY KEY,
user_id NUMERIC NOT NULL,
account_id NUMERIC NOT NULL,
category_id NUMERIC NOT NULL,
amount DOUBLE NOT NULL, date VARCHAR(25) NOT NULL,
description VARCHAR(25),
FOREIGN KEY(account_id) REFERENCES account(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(category_id) REFERENCES category(id)
);
to find what is wrong i was adding one column after another, and i noticed i cant create table with more than two foreign keys, is it limit or am i doing something wrong? can i walk this around somehow? im not interested in this case, because i realized i need to change design of my db anyway
regards
VARCHAR is wrong.
Should be TEXT
DOUBLE should be REAL

Resources