Squeryl Foreign Key onDelete cascade doesn't work - scala

i have a User and a Device Table. If a User connects to a Device, the Device will know its User (Foreign Key). A Device can only have one User.
I create a Foreign Key with
userToDevice.foreignKeyDeclaration.constrainReference(onDelete cascade)
it does alter the table like that
alter table Device add constraint DeviceFK10 foreign key (user_id) references User(id) on delete cascade;
Now, when i create a User, assign it to a Device and then delete the User, the user_id property at Device Table doesn't get deleted, too.
//CREATE DEVICE
val device = queries.deviceCreate("XYZ-Device", None) //None User
//ASSIGN USER TO DEVICE
update(deviceT)(d=> where(d.id === device.get.id) set(d.user_id := user.id))
//DELETE USER
userTable.deleteWhere(u=> u.id === user.id)
Why is it that it doesn't delete the Foreign Key even with on delete cascade?
EDIT:
I think i messed anything up with the relation.
Here you can see example code. Probably you can tell me what i am doing wrong here.
ShowCase on Github
EDIT2:
It seems like mysql doesn't even create the Foreign Key. I can't find any when i check localhost/phpmyadmin

I think the default table type for MySQL is MyISAM, which doesn't support foreign keys.

Related

How do I define the main/primary record of a one-to-many relationship?

I'm making a service with an account table and a profile table. An account can own multiple profiles, but accounts always have a primary profile. This would initially be the first profile created alongside the account upon registration, but the user could add profiles and set one as the primary profile later.
I've tried the following setup:
create table account (
id uuid primary key,
email text unique,
phone text unique,
created_at timestamptz,
primary_profile_id uuid references profile on delete restrict,
);
create table profile (
id uuid primary key,
account_id uuid references account on delete cascade,
username text unique,
about text,
created_at timestamptz
);
This doesn't work because:
You can't even run that to create the tables since they both rely on the other existing beforehand. A workaround would be to create the account table without primary_profile_id and alter the table to add that column after the creation of the profile table, however...
Even if you can create the tables, you can't add records to them because you would need the other to exist first to reference it. It is technically possible if you leave primary_profile_id as NULL and change it after the profile has been created, but the columns aren't supposed to be nullable, so it's not really ideal.
Is there any good solution to this? I've also considered having a primary boolean on the profile table, but then there's nothing on the database side preventing that being true for multiple profiles under a single account.
Thanks for any help :)
Your idea of enforcing your requirement with a foreign key is good.
Creating the tables is no problem; you can simply run
create table account (
id uuid primary key,
email text unique,
phone text unique,
created_at timestamptz,
primary_profile_id uuid,
);
create table profile (
id uuid primary key,
account_id uuid references account on delete cascade,
username text unique,
about text,
created_at timestamptz
);
ALTER TABLE account
ADD FOREIGN KEY (primary_profile_id) REFERENCES profile
DEFERRABLE INITIALLY DEFERRED;
A deferred foreign key constraint like that is not checked right when a row is inserted, but at the end of the transaction. So you can add account first and then the matching profile, as long as you Insert both in the same transaction.
I recommend using NOT NULL in your column definitions wherever possible.

use one part of composite primary key as foreign key

I'm using PostgreSQL.
I have a table accounts with account_id as the primary key. I also have a second table called relations with a composite primary key (follower_id, following_id). Each relation must be unique.
ALTER TABLE accounts ADD CONSTRAINT users_pk PRIMARY KEY (account_id);
ALTER TABLE relations ADD CONSTRAINT relations_pk PRIMARY KEY (follower_id, following_id);
I want to create a foreign key constraint from follower_id (relations) -> account_id (accounts), and the same with following_id.
ALTER TABLE relations ADD CONSTRAINT follower_id_fk FOREIGN KEY (follower_id) REFERENCES accounts (account_id) ON DELETE CASCADE
This foreign key is not accepted by the database. I get the following error:
ERROR: insert or update on table "relations" violates foreign key constraint "follower_id_fk"
DETAIL: Key (follower_id)=(4) is not present in table "accounts".
I understand this, because it's a composite primary key.
What I want to achieve:
When an account is deleted, I want to delete all the records where the account_id is the follower_id (ON DELETE CASCADE) AND where it is the following_id.
I could do this in my nodejs code or with a trigger function, but I don't know what will be the best performance-wise. Does anyone knows a/the best solution?

Postgres inheritance and foreign keys or alternative

I use postgres inheritance in my project.
For example: I have a "user" table and "user_child" that inherits from the "user" table.
I have two records: the first record is created in the user table, the second record is created in the user_child table, while the record from user_child is partially stored in user due to inheritance.
I also have a third table - "homework", it has a column assigned_user - a foreign key to the user table.
When I add an record to the "task" table where the "assigned_user" field refers to a record from the user table, then everything is fine, but when I select a record from the user_child table, I get an error:
ERROR: insert or update on table "homework" violates foreign key
constraint "fk-homework-assigned_user""
DETAIL: Key (assigned_user)=(3) is not present in table "user".
Deleting a constraint helps solve my problem, but I want to use cascading deletion and updating records. Can you tell me what alternatives are there or what I'm doing wrong?
PostgreSQL inheritance doesn't quite work how you expect. Yes, you can see info from the child tables when querying the parent table, but this does not extend to foreign key relationships. The row "belongs" to the child, not the parent. The foreign key reference doesn't touch the child.
It's generally a bad idea to use inheritance in PostgreSQL except for specific cases like making a temporal system or enforcing naming conventions (like interfaces in OOP rather than state inheritance).
PostgreSQL inheritance can be very powerful, but it is generally overused in my opinion. There is already a solution (and cross-database compatible) that more closely follows the traditional relational model.
A better model that would do what you seem to want is the following:
CREATE TABLE "user" (
user_id serial PRIMARY KEY, -- Or UUID or generated column in newer versions
-- other fields that all "children" should share
);
CREATE TABLE user_child (
user_id integer NOT NULL
REFERENCES "user" (user_id) ON UPDATE CASCADE ON DELETE CASCADE,
-- other fields specific to the child
);
CREATE TABLE homework (
homework_id serial PRIMARY KEY,
user_id integer NOT NULL
REFERENCES "user" (user_id) ON UPDATE CASCADE ON DELETE RESTRICT,
-- other fields specific to homework
);
The equivalent to your query for user_child is
SELECT u.user_id
FROM "user" AS u
INNER JOIN user_child AS uc;
And to query user, both parent and child would still be
SELECT u.user_id
FROM "user" AS u;
Adding an inner join is pretty trivial and could be hidden behind a view. Now your foreign key reference to "user" will function correctly.

implement foreign Key in JPA side( in database this relation is nt implemented)

how to implement Foreign key relation in JPA side ( There is no foreign key for this relation in db, Db owned by another application , i cant able to change db structure( SW vendor not allowing me to do it)
Is there just no foreign key constraint, or nothing referencing the id at all?
If there is just no constraint, then it does not matter, JPA does not care if there is a constraint or not, just use the column that references the id.
If there is nothing referencing the id, then you cannot have a relationship with nothing store it. If you cannot alter the table, then perhaps you can add a new table that defines the join between the two tables (similar to a many to many, but JPA also allows a join table to be used for a one to one).

Problem adding foreign key in simple setup

I have two tables
Users
Users_Role
I decided to try to add a foreign key as to my understanding it will let me cascade the delete procedure when removing a user from Users (as well as enforce integrity).
So via Management Studio I right clicked my Users_Role table, Design, then went into Relationships. I added a new relationship between the two tables as such:
Foreign Key Base Table: Users_Role
Foreign Key Columns: UserID
Primary/Unique Key Base: Users
Primary/Unique Key columns: ID
When I then try to save, I get the following error:
'Users' table saved successfully
'Users_Role' table
- Unable to create relationship 'FK_Users_Role_Users'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Users_Role_Users". The conflict occurred in database "db", table "dbo.Users", column 'ID'.
I'm not sure what's going on. Adds the relationship to Users, but not Users_Role? The only thing special about Users_Role is that my primary key consists of two columns, UserID and Role (the only two columns in the table, if that matters). Otherwise, nothing special.
This error means that in your current database, you have entries in the "Users_Role" table which have a "UserID" value that is not present in the Users table as ID.
You first need to find those "rogue" rows and either update or delete them, before you can create the foreign key to enforce referential integrity and avoid such problems in the future.
You can find those by issuing this command:
SELECT * FROM Users_Role
WHERE UserID NOT IN
(SELECT DISTINCT ID FROM Users)