I read all the previous issues with the foreign keys. I did all the possible configurations but I can not enforce it to work.
I can insert to the nodes table even if I don't have any record in the types table. But as I know the foreign key constraint should not allow this to happen.
CREATE TABLE nodes(
id int NOT NULL PRIMARY KEY ,
ver int NOT NULL,
lock int NOT NULL,
title varchar(50) NOT NULL,
typeid int NOT NULL REFERENCES types(id),
desc text NOT NULL,
CHECK(trim(id) <> '' AND trim(ver) <> '' AND trim(lock) <>'' AND trim(title)
<> '' AND trim(typeid) <> '' AND trim(desc) <> '' )
)
and
CREATE TABLE "types"
("id" INTEGER PRIMARY KEY NOT NULL ,
"name" TEXT NOT NULL )
SQLite 3.19.3
sqlite> PRAGMA foreign_keys;
foreign_keys
------------
1
sqlite> PRAGMA foreign_keys_list;
sqlite>
I don't know why PRAGMA foreign_keys_list answer is empty.
It is solved because I used s in my command
Correct : PRAGMA foreign_key_list(nodes)
sqlite> PRAGMA foreign_key_list(nodes);
id seq table from to on_update on_delete match
---------- ---------- ---------- ---------- ---------- ---------- -------- ------------
0 0 types typeid id NO ACTION NO ACTION NONE
The syntax is PRAGMA foreign_key_list(table-name);
Remove that s after key — SQlite won't warn you if you made a typo and simply returns nothing.
Related
It give me error example image at below:
Trigger code:
CREATE OR REPLACE TRIGGER InsertNewStaffs
BEFORE INSERT ON Staffs
FOR EACH ROW
ENABLE
DECLARE
v_user varchar(255);
v_date varchar(255);
v_Staffs_ID Staffs.Staffs_ID%TYPE;
v_Staffs_Name Staffs.Staffs_Name%TYPE;
v_Staffs_Contact_Number Staffs.Staffs_Contact_Number%TYPE;
v_Staffs_Email Staffs.Staffs_Email%TYPE;
v_Orders_ID Staffs.Orders_ID%TYPE;
v_count INTEGER;
BEGIN
SELECT count(*) INTO v_count FROM Staffs
WHERE Staffs_ID = v_Staffs_ID OR
Staffs_Name = v_Staffs_Name OR
Staffs_Contact_Number = v_Staffs_Contact_Number OR
Staffs_Email = v_Staffs_Email;
IF v_count > 0 THEN
RAISE_APPLICATION_ERROR(-20000, 'Oops, some data is already exists. Please try again...');
DBMS_OUTPUT.PUT_LINE('Oops, some data is already exists. Please try again...');
SELECT user, TO_CHAR(sysdate, 'DD/MON/YYYY HH24:MI:SS') INTO v_user, v_date FROM dual;
ELSE
INSERT INTO Staffs(Staffs_ID, Staffs_Name, Staffs_Contact_Number, Staffs_Email, Orders_ID)
VALUES(v_Staffs_ID, v_Staffs_Name, v_Staffs_Contact_Number, v_Staffs_Email, v_Orders_ID);
DBMS_OUTPUT.PUT_LINE('One Row Inserted By ' || v_user || CHR(10));
DBMS_OUTPUT.PUT_LINE('Inserted data at ' || v_date);
INSERT INTO monitorInsertStaffs(user_name, entry_date, operation)
VALUES(v_user, v_date, 'Insert');
END IF;
END;
/
My Table:
CREATE TABLE Staffs(
Staffs_ID char(20) NOT NULL,
Staffs_Name varchar(255) NOT NULL,
Staffs_Contact_Number varchar(50) NOT NULL,
Staffs_Email varchar(255) NOT NULL,
Orders_ID char(20),
PRIMARY KEY (Staffs_ID),
FOREIGN KEY (Orders_ID) REFERENCES Orders(Orders_ID)
);
CREATE TABLE Orders(
Orders_ID char(20) NOT NULL,
Order_Date DATE NOT NULL,
Order_Status varchar(255) NOT NULL,
Order_Quantity int NOT NULL,
Order_TotalAmount NUMERIC(10,2) NOT NULL,
Order_TotalPrice NUMERIC(10,2) NOT NULL,
PRIMARY KEY (Orders_ID),
Pets_Products_ID char(20),
CustomerID char(20),
FOREIGN KEY (Pets_Products_ID) REFERENCES Pets_Products(Pets_Products_ID),
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);
I try to insert data and if the data has existed it will show RAISE_APPLICATION_ERROR(-20000, 'Oops, some data is already exists. Please try again...'); but it didn't show the message and also cannot insert data when no exists the data.
I don't know where is error code that I find.
The whole concept is just wrong.
you've based trigger on a table into which you're just inserting a row (staffs)
then you're selecting from the same table (it'll raise the mutating table error if you try to insert more than a single row)
the where clause uses local variables that have no values
insert into staffs cause the same trigger to fire over and over again, until Oracle concludes that that's enough and raises the error
Don't use a trigger. Use UNIQUE constraints:
CREATE TABLE Staffs(
Staffs_ID char(20) NOT NULL,
Staffs_Name varchar(255) NOT NULL,
Staffs_Contact_Number varchar(50) NOT NULL,
Staffs_Email varchar(255) NOT NULL,
Orders_ID char(20),
PRIMARY KEY (Staffs_ID),
UNIQUE (Staffs_Name),
UNIQUE (Staffs_Contact_Number),
UNIQUE (Staffs_Email),
FOREIGN KEY (Orders_ID) REFERENCES Orders(Orders_ID)
);
(However, you should also consider whether your business requirements make sense or if you can have multiple staff members called Jane Smith or if you can have two staff members who share an office with the same telephone number?)
If you want to use a logging table then use an autonomous transaction to just insert into that table:
CREATE OR REPLACE TRIGGER InsertNewStaffs
BEFORE INSERT ON Staffs
FOR EACH ROW
ENABLE
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO monitorInsertStaffs(
user_name, entry_date, operation
) VALUES(
:NEW.Staffs_ID, SYSDATE, 'Insert'
);
COMMIT;
END;
/
db<>fiddle here
I have prepared a huge list of sql statements (INSERT calls)s in a file which I run from sqlite3 terminal with
.read tmp/commands.sql
When I run the command one or more times in session #1 all goes well with no error and result as expected the ignore prevents against error messages for the duplicates).
Now if I quit sqlite3 with .quit then immediately come back and run the same command .read tmp/commands.sql I get for each sql call in my commands.sql an error message "Error: near line xxx: FOREIGN KEY constraint failed"
My database is made of two tables with a relation
a foreign key is defined in the second table to link to the fist one on its unique ID (FolderID)
in the beginning of the sql script, I added PRAGMA foreign_keys = true; to I thought allow relations
Can you please explain why this is happening in the second session?
Thanks
The first call in the commands.sql file will look like this
PRAGMA foreign_keys = true;
/*
------------------------------------------------------------------
adding data in Folders for '0003_Runs/HiSeq2500/190921_7001450_0495_AH5JJ7BCX3
------------------------------------------------------------------
*/
INSERT OR IGNORE INTO Folders
(
Creator,
CreatorVersion,
DBAddDate,
FolderPath,
FolderName,
FolderSize,
Protection,
DeviceModel,
StartDate,
DeviceID,
RunNr,
FlowCellID,
ProjectNR,
Status,
DeliveryDate,
Comment
)
VALUES (
"AddIlluminaFolders2",
" 1.0; 2020-09-11",
"1600864879",
"0003_Runs/HiSeq2500",
"190921_7001450_0495_AH5JJ7BCX3",
"183173644288",
"0",
"HiSeq2500",
"190921",
"7001450",
"0495",
"AH5JJ7BCX3",
"",
"done",
"",
""
);
/*
------------------------------------------------------------------
adding data in Actions for 0003_Runs/HiSeq2500/190921_7001450_0495_AH5JJ7BCX3
------------------------------------------------------------------
*/
INSERT OR IGNORE INTO Actions
(
FolderID,
Creator,
CreatorVersion,
ActionDate,
ActionName,
Comment
)
VALUES (
last_insert_rowid(),
"AddIlluminaFolders2",
" 1.0; 2020-09-11",
"1600864879",
"AddIlluminaFolders2",
""
);
-- ----------------------------------------------------------------
followed by many other blocks of the same kind until end of file with PRAGMA foreign_keys = true;
Here is my full table definition
/*
Database structure for NCDataMngr and BigData_viewer
Author: Stéphane Plaisance - VIB-Nucleomics Core
database version: 1.0 - 2020-09-11
File Encoding : utf-8
REM: edit below if you change the database schema
=> INSERT INTO "version" (vnum, vdate) VALUES ("1.0", "2020-09-11");
*/
PRAGMA foreign_keys = false;
-- ----------------------------
-- Table structure for Folders
-- ----------------------------
DROP TABLE IF EXISTS "Folders";
CREATE TABLE "Folders" (
"FolderID" INTEGER NOT NULL PRIMARY KEY,
"Creator" TEXT(255,0),
"CreatorVersion" TEXT(255,0),
"DBAddDate" TEXT(255,0),
"FolderPath" TEXT(255,0) NOT NULL,
"FolderName" TEXT(255,0) NOT NULL,
"FolderSize" INTEGER(20,0),
"Protection" INTEGER(1,0),
"DeviceModel" TEXT(255,0),
"StartDate" TEXT(255,0),
"DeviceID" TEXT(255,0),
"RunNr" TEXT(255,0),
"FlowCellID" TEXT(255,0),
"ProjectNR" TEXT(255,0),
"Status" TEXT(255,0),
"DeliveryDate" TEXT(255,0),
"Comment" TEXT(255,0)
);
INSERT INTO "main".sqlite_sequence (name, seq) VALUES ("Folders", '0');
-- ----------------------------
-- Table structure for Actions
-- ----------------------------
DROP TABLE IF EXISTS "Actions";
CREATE TABLE "Actions" (
"FolderID" INTEGER NOT NULL,
"ActionID" INTEGER NOT NULL PRIMARY KEY,
"Creator" TEXT(255,0),
"CreatorVersion" TEXT(255,0),
"ActionDate" TEXT,
"ActionName" TEXT(255,0),
"Comment" TEXT(255,0),
CONSTRAINT "Folders2Actions" FOREIGN KEY ("FolderID") REFERENCES "Folders" ("FolderID") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "main".sqlite_sequence (name, seq) VALUES ("Actions", '0');
-- ----------------------------
-- Table structure for version
-- ----------------------------
DROP TABLE IF EXISTS "version";
CREATE TABLE "version" (
"vnum" text,
"vdate" text
);
INSERT INTO "main".sqlite_sequence (name, seq) VALUES ("version", '0');
INSERT INTO "version" (vnum, vdate) VALUES ("1.1", "2020-09-23");
-- ----------------------------
-- View structure for ActionView
-- ----------------------------
DROP VIEW IF EXISTS "ActionView";
CREATE VIEW "ActionView" AS SELECT
Actions.*,
Folders.FolderName
FROM
Actions
INNER JOIN Folders ON Folders.FolderID = Actions.FolderID
ORDER BY
Actions.FolderID ASC,
Actions.ActionID ASC;
-- ----------------------------
-- View structure for FolderView
-- ----------------------------
DROP VIEW IF EXISTS "FolderView";
CREATE VIEW "FolderView" AS SELECT
Folders.*
FROM
Folders
ORDER BY
Folders.FolderID ASC;
-- ----------------------------
-- Indexes structure for table Folders
-- ----------------------------
CREATE UNIQUE INDEX "idx_Folders_FolderPath_FolderName" on Folders ( "FolderPath", "FolderName" );
-- ----------------------------
-- Indexes structure for table Actions
-- ----------------------------
CREATE INDEX "idx_Actions_FolderID" ON Actions ("FolderID" ASC);
CREATE UNIQUE INDEX "idx_Actions_FolderID_Creator" ON Actions ("FolderID" ASC, "Creator");
PRAGMA foreign_keys = true;
last_insert_rowid(). When commands.sql is run mutliple times in the same session, last_insert_rowid() has the value of the last row inserted. Which will never give a FOREIGN KEY failure. When a new session is invoked, no rows are inserted (because of the "dupes"), last_insert_rowid() has value 0, thus FOREIGN KEY violation on Actions insert.
For some reason, I cannot get FOREIGN KEY to work.
Any INSERT into primary_specs will go through, despite the 'ad_ids' table being empty.
EDIT: for some reason the INSERT will NOT go through when using DB Browser, but my python script waltzes right pass that constraint and is able to save the data...
Main table:
CREATE TABLE "ad_ids" (
"ad_id" INTEGER,
"ad_url" TEXT,
PRIMARY KEY("ad_id")
)
Secondary table:
CREATE TABLE "primary_specs" (
"ad_id" INTEGER,
"version" TEXT,
"year" INTEGER,
PRIMARY KEY("ad_id"),
FOREIGN KEY("ad_id")
REFERENCES ad_ids("ad_id")
)
PRAGMA foreign_key_list(primary_specs);
returns:
id seq table from to on_update on_delete match
0 0 ad_ids ad_id ad_id NO ACTION NO ACTION NONE
PRAGMA foreign_keys
returns 1
Apparently PRAGMA foreign_keys = ON; is applied on connection and not a database.
I've a Rate table with the following structre:
CREATE TABLE Rate (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id INTEGER,
value INTEGER,
user_id INTEGER,
FOREIGN KEY(user_id) REFERENCES User(ID),
FOREIGN KEY(book_id) REFERENCES book(ID) ON DELETE RESTRICT
)
And a book table with the following structure:
DROP TABLE IF EXISTS Book;
CREATE TABLE Book (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
ISBN VARCHAR,
author_id INTEGER,
editor_id INTEGER,
translator_id INTEGER,
publisher_id INTEGER,
"type" VARCHAR,
language VARCHAR,
"date" VARCHAR,
format VARCHAR,
summary TEXT,
FOREIGN KEY(author_id) REFERENCES Author(ID) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY(editor_id) REFERENCES Editor(ID) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY(translator_id) REFERENCES Translator(ID) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY(publisher_id) REFERENCES Publisher(ID) ON DELETE SET NULL ON UPDATE CASCADE
);
So, if I have a Rate entry like this:
1 1 4 3(ID, BOOK_ID, VALUE, USER_ID)
I shouldn't be able to delete the Book with the ID 1, right?
This is exactly what happens when I try to delete the Book with ID 1 on SQLITE Manager. It gives me
FOREIGN KEY constraint failed
However, when I call my delete from the code, it totally ignores the restriction and deletes the book and there's no change in the Rate entry it is still:
1 1 4 3
And my delete method is like the following:
public void delete() {
try {
String query = "DELETE FROM book WHERE id = ? ";
PreparedStatement statement = db.prepareStatement(query);
statement.setInt(1, (Integer) this.id);
statement.executeUpdate();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
When i run PRAGMA foreign_keys on SQLITE Manager it returns 1. So, I assume that the database is created correctly.
The documentation says:
... foreign key constraints ... must still be enabled by the application at runtime, using the PRAGMA foreign_keys command. For example:
PRAGMA foreign_keys = ON;
Foreign key constraints are disabled by default (for backwards compatibility), so must be enabled separately for each database connection.
according to this null foreign keys are allowed unless and until we are adding the appropriate "NOT NULL" constraint to the schema.
but I am seeing the some different behavior,
sqlite> PRAGMA Foreign_keys;
1
sqlite> create table proc (
sqlite> pid integer,
sqlite> name text,
sqlite> ppid integer,
sqlite> foreign key (ppid) references proc (id)
sqlite> );
sqlite> .schema proc
CREATE TABLE proc (
pid integer,
name text,
ppid integer,
foreign key (ppid) references proc (id)
);
sqlite> insert into proc (pid, name, ppid)
sqlite> values (0, "init", null);
Error: foreign key mismatch
sqlite> PRAGMA Foreign_keys=OFF;
sqlite> PRAGMA Foreign_keys;
0
sqlite> insert into proc (pid, name, ppid)
sqlite> values (0, "init", null);
sqlite> select * from proc;
0|init|
how can I allow null foreign key in sqlite when PRAGMA foreign_keys=ON? or it is not possible at all?
The ID column is named pid, not id.
The parent key column must have a UNIQUE or PRIMARY KEY constraint.
Try adding a foreign key clause by changing your table create statement to:
CREATE TABLE proc (pid integer, name text, ppid integer, foreign key (ppid) references
proc (id) ON UPDATE CASCADE ON DELETE SET NULL);