sqlite- interlinking two database tables using foreign keys - sqlite

In SQL in general, but in SQLite for this case, can we establish a foreign key from one table say, table in db1.db to mainTable in db2.db. That is we can use a foreign key relationship in table by referencing the primary key in mainTable, the main idea being to use this relationship to trigger ON DELETE CASCADE. (Briefly in my case, mainTable happens to be a system maintained SQLITE database, which I'd like to avoid manual finding and analyzing. If I could somehow access establish this key, life would be a lot easier).

Related

PostgreSQL 11 foreign key on partitioning tables

In the PostgreSQL 11 Release Notes I found the following improvements to partitioning functionality:
Add support for PRIMARY KEY, FOREIGN KEY, indexes, and triggers on partitioned tables
I need this feature and tested it.
Create table:
CREATE TABLE public.tbl_test
(
uuid character varying(32) NOT null,
registration_date timestamp without time zone NOT NULL
)
PARTITION BY RANGE (registration_date);
Try to create Primary key:
ALTER TABLE public.tbl_test ADD CONSTRAINT pk_test PRIMARY KEY (uuid);
I get an error SQL Error [0A000]. If use composite PK (uuid, registration_date) then it's work. Because PK contains partitioning column
Conclusion: create PK in partitioning tables work with restrictions (PK need contains partitioning column).
Try to create Foreign key
CREATE TABLE public.tbl_test2
(
uuid character varying(32) NOT null,
test_uuid character varying(32) NOT null
);
ALTER TABLE tbl_test2
ADD CONSTRAINT fk_test FOREIGN KEY (test_uuid)
REFERENCES tbl_test (uuid);
I get an error SQL Error [42809]. It means FOREIGN KEY on partitioning tables not work.
Maybe i'm doing something wrong. Maybe somebody tried this functionality and know how this work.
Maybe somebody know workaround except implement constraint in the application.
PostgreSQL v12.0 will probably support foreign keys that reference partitioned tables. But this is still not guaranteed as v12.0 is still in development.
For v11 and lower versions, you may use triggers as described by depesz in these posts: part1, part2, and part3.
Update: PostgreSQL v12.0 was released on Oct 3, 2019, with this feature included
Postgres 11 only supports foreign keys from a partitioned table to a (non-partitioned) table.
Previously not even that was possible, and that's what the release notes are about.
This limitation is documented in the chapter about partitioning in the manual
While primary keys are supported on partitioned tables, foreign keys referencing partitioned tables are not supported. (Foreign key references from a partitioned table to some other table are supported.
(emphasis mine)

Foreign key in main database referencing attached database

Is there any way in SQLite3 to have a foreign key in the main database that references columns in an attached database (or vice-versa?)
I hope to share the attached (read-only) database between multiple processes, each of which has its own (read/write) main database.
I create the parent table like this (in database 'ParentDB'):
create table Parent (id integer primary key);
Now I try this in the main database:
attach 'parent.sqlite3' as ParentDB;
create table Child (id integer not null references Parent (id),
constraint PK_Child primary key (id));
insert into ParentDB.Parent (id) values (42);
When I try it it creates the foreign key with no errors. Now I try to insert a row into the child table:
insert into Child (id) values (42);
And I get this error:
Error: no such table: main.Parent
So it seems it always assumes the parent and child tables belong to the same database.
Also the foreign key syntax does not allow you to specify which database the parent table belongs to.
Is there a workaround?
This question is related, but here both the parent and child tables are in the same attached database, whereas I have them in separate databases.
SQLite's built-in foreign key constraints do not work across databases.
The only workaround would be to manually write check constraints and triggers that do the same checking.

SQLite: Delete Rule Capabilities With Reflexive Joins?

I am attempting to use foreign key support in SQLite to maintain referential integrity on a single-table database that has a reflexive join.
e.g.
PRAGMA foreign_keys = ON;
create table tree (
objectId text unique not null,
parentObjectID text,
foreign key (parentObjectID) references tree(parentObjectID) on delete cascade
)
The behavior that I am hoping for is that when a parent row is deleted, its children and their children are deleted as well.
However, when I attempt to delete the root row (where the expected behavior would be that every other row in the database is also deleted), I get this error:
sqlite> delete from tree where objectid = '0';
Error: foreign key mismatch
Are my expectations out of whack with with SQLite foreign key support (and delete behaviors) can provide?
Your problem is pretty simple, your FK on parentObjectId references parentObjectId rather than objectId and SQLite doesn't detect this bit of confusion until you try to use the table. If your FK is defined like this:
foreign key (parentObjectID) references tree(objectID) on delete cascade
From the fine manual:
So, in other words, misconfigured foreign key constraints that require looking at both the child and parent are DML errors. The English language error message for foreign key DML errors is usually "foreign key mismatch" but can also be "no such table" if the parent table does not exist. Foreign key DML errors are may be reported if:
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.
The third point would seem to apply here since parentObjectId is neither a PK nor constrained to be unique so that's why you don't see an error until you try to modify the table's content (i.e. use a DML statement rather than a DDL statement).

How to implement a cross-database foreign key constraint?

Let's say I have two schemas: HR and Orders.
[HR].Employees [Orders].Entries
-------------- ----------------
Id_Employee ----> Employee
Fullname Id_Entry
Birthday Description
Amount
As you can see, what I'd want is to be able to establish a cross-database foreign key, but when I try this using a database link, I get:
-- From [Orders]
ALTER TABLE Entries
ADD CONSTRAINT FK_Entries_Employees FOREIGN KEY (Employee)
REFERENCES Employees#HR;
COMMIT;
ORA-02021: DDL operations are not allowed on a remote database
Is there a way around this? It's a legacy database, so I can't change the existing schema.
For the NHibernate crowd: I would then use this relation to map the NHibernate's domain objects.
One option would be to create a materialized view of Employees on [Orders] and then use that as the parent for the foreign key.
Of course, that has some drawbacks. In particular,
-- you won't be able to do a complete refresh of the materialized view without disabling the foreign key, so it'll have to fast refresh.
-- keys entered into EMPLOYEES won't be available to ENTRIES until the materialized view refresh. If that's critical, you may want to set it to refresh on commit.
Other alternatives are to handle the key enforcement yourself through a trigger or through a post cleanup process. Or convince the DBA's that these schemas can reside on the same database instance.
As far as I know constraints and referential integrity are only supported within one single database.
If you need to cross the boundaries of the database, you'd have to be creative. Maybe write some triggers checking for data in the other database or enforce these constraints on the application level. But then you may encounter the problem with transaction scope limited to one single database.

Does a SQLite Foreign key automatically have an index?

I know that SQLite does not enforce foreign keys natively, but that's not my primary concern. The question is: If I declare
CREATE TABLE invoice (
invoiceID INTEGER PRIMARY KEY,
clientID INTEGER REFERENCES client(clientID),
...
)
will sqlite at least use the information that clientID is a foreign key to optimize queries and automatically index invoice.clientID, or is this constraint a real no-op?
In the SQLite Documentation it says:
... "an index should be created on the child key columns of each foreign key constraint"
ie. the index is not automatically created, but you should create one in every instance.
Even if it is not actually a no-op (a data structure describing the constraint is added to the table), foreign key related statement doesn't create any index on involved columns.
Indexes are implicitly created only in the case of PRIMARY KEY and UNIQUE statements.
For more details, check it out build.c module on the sqlite source tree:
http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/build.c https://www.sqlite.org/src/file?name=src/build.c&ci=tip

Resources