How to solve multiple cascade paths? - sql-server

In my database, I have a Person and Member table. The Member table has 2 foreign keys which both reference the same column in the People Table. The constraints look like this:
CONSTRAINT [FK_Members_People_1]
FOREIGN KEY ([PersonID])
REFERENCES [People].[People]([ID])
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT [FK_Members_People_2]
FOREIGN KEY ([EnquiryTakenBy])
REFERENCES [People].[People]([ID])
ON DELETE SET NULL
ON UPDATE NO ACTION
The error I get is as follows:
Introducing FOREIGN KEY constraint 'FK_Members_People_2' on table 'Members' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
How would I go about solving this?
Basically this is the behaviour I'm trying to get:
When the record referenced by PersonID is removed. I need it to delete all child records in other tables. (There's 8 child tables)
When the record referenced by EnquiryTakenBy is deleted. I need EnquiryTakenBy to be set to null.
EDIT: Table structure is as follows:
CREATE TABLE [People].[People]
(
[ID] INT NOT NULL IDENTITY,
[PersonType] INT NOT NULL,
[Forename] VARCHAR(16) NOT NULL,
[Surname] VARCHAR(32) NOT NULL,
[Gender] CHAR(1) NOT NULL,
[DateOfBirth] DATE NULL,
[HobbiesAndInterests] VARCHAR(256) NULL,
[AdditionalInformation] VARCHAR(512) NULL,
[LocalCentre] INT NOT NULL DEFAULT 0,
CONSTRAINT [PK_People] PRIMARY KEY ([ID]),
CONSTRAINT [FK_People_PersonType]
FOREIGN KEY ([PersonType])
REFERENCES [Lookups].[PersonTypes]([ID])
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT [FK_People_Centres]
FOREIGN KEY ([LocalCentre])
REFERENCES [Lookups].[Centres]([ID])
ON DELETE CASCADE
ON UPDATE CASCADE
)
CREATE TABLE [People].[Members]
(
[PersonID] INT NOT NULL,
[IsActive] BIT NOT NULL DEFAULT 0,
[Issues] VARCHAR(500) NULL,
[InTreatment] BIT NOT NULL DEFAULT 0,
[ProblemSubstance] VARCHAR(64) NOT NULL,
[WantsHelpWith] VARCHAR(128) NULL,
[EnquiryTakenBy] INT NOT NULL,
[IsVolunteer] BIT NOT NULL DEFAULT 0,
CONSTRAINT [PK_Members] PRIMARY KEY ([PersonID]),
CONSTRAINT [FK_Members_People_1]
FOREIGN KEY ([PersonID])
REFERENCES [People].[People]([ID])
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT [FK_Members_People_2]
FOREIGN KEY ([EnquiryTakenBy])
REFERENCES [People].[People]([ID])
ON DELETE SET NULL
ON UPDATE NO ACTION
)

Ok, found a solution. Apparently my problem was something to do with SQL Server didn't know which constraint took precedence, so I replaced the second foreign key constraint with this trigger:
CREATE TRIGGER Member_UpdateEnquiryID ON People.People
AFTER DELETE
AS
BEGIN
DECLARE #id int = (select id from deleted);
UPDATE People.Members
SET EnquiryTakenBy = NULL
where EnquiryTakenBy = #id
END

Related

Update/Delete violate foreign key on either side

I have two tables, below are the strutures
CREATE TABLE IF NOT EXISTS nl_address (
id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
address_text varchar(100),
pincode varchar(6),
city_id int NOT NULL,
state_id int NOT NULL,
country_id int NOT null,
is_active boolean default true,
PRIMARY KEY (id),
CONSTRAINT fk_city_id FOREIGN KEY(city_id) REFERENCES nl_city(id),
CONSTRAINT fk_state_id FOREIGN KEY(state_id) REFERENCES nl_state(id),
CONSTRAINT fk_country_id FOREIGN KEY(country_id) REFERENCES nl_country(id)
);
CREATE TABLE IF NOT EXISTS nl_customer (
cust_id int NOT NULL,
prefix varchar(10) default 'CUST-',
suffix varchar(2),
org_name varchar(100) NOT NULL,
domain_name varchar(100) NOT NULL,
pan_number varchar(10) NOT null,
pri_contact varchar(10) NOT NULL,
pri_number varchar(10) NOT NULL,
pri_email varchar(30) NOT NULL,
sec_contact varchar(10),
sec_number varchar(10),
sec_email varchar(30),
is_active boolean default true,
addr_id int not null,
created_date date,
created_by varchar(10),
updated_date date,
updated_by varchar(10),
PRIMARY KEY (cust_id),
CONSTRAINT fk_address_id FOREIGN KEY(addr_id) REFERENCES nl_address(id)
);
The problem is, neither I am able to update or delete
If i am trying to update record in nl_address, I got an violation error that the field is used inside `nl_customer.
If i tried to update from nl_customer, then I got an violation error that the field is used inside nl_address
It was originated, when JPA trying to persist the data, I have inserted a dummy data with id 1, when JPA trying to insert another record then it throws
.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "nl_address_pkey"
Detail: Key (id)=(1) already exists.
It seems there is something wrong with the table structure, any help appreciated
Actually this is common that you cannot update or delete that belong to primary/foreign key if you generate duplicates, as all values should be unique (i.e. if you have already id=1 and update id=2 to id=1, you will get the error you mentioned) and because a foreign key construct is a specific relationship it should be clarified what will happen with this relationship.
In case of 'nl_address' you used 'GENERATED BY DEFAULT AS IDENTITY' which have the same purpose as SERIAL (i.e. auto increment), but it is more compliant with SQL standard. (I assume you are also aware of difference between GENERATED BY DEFAULT and GENERATED ALWAYS)
However, you can specify the sequence in order to ensure the proper auto increment functionality.
ALTER TABLE nl_address
ALTER COLUMN "id"
DROP IDENTITY IF EXISTS;
ALTER TABLE nl_address
ALTER COLUMN "id"
ADD GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT 1);
If you use UPDATE or DELETE on FOREIGN KEY construct ensure what should happen with relationship:
[CONSTRAINT fk_name]
FOREIGN KEY(fk_columns)
REFERENCES parent_table(parent_key_columns)
[ON DELETE delete_action]
[ON UPDATE update_action]
/* as delete_action or update_action you can use e.g. SET NULL, RESTRICT or CASCADE;
so ensure what happen with records in related table*/

Enforce 1:0..1 relationship with EF6 Database First

In my model, I have three tables, Storage, Haul and StoragePlace. One storage can either be a place or haul. For the StoragePlace, I already achieved a 1:0..1 relationship. The problem is the Haul entity.
CREATE TABLE dbo.Haul
(
ID INT NOT NULL PRIMARY KEY IDENTITY,
ID_Storage INT NOT NULL UNIQUE,
Arrival DATETIME NOT NULL DEFAULT getdate(),
Depature DATETIME NULL,
CONSTRAINT FK_Haul_to_Storage FOREIGN KEY (ID_Storage) REFERENCES Storage(ID) ON DELETE CASCADE
)
GO
/** --- See edit below --
CREATE UNIQUE NONCLUSTERED INDEX UQX_Storage
ON Haul(ID_Storage)
WHERE ID_Storage IS NOT NULL;
GO
**/
--------------------------------------------------
CREATE TABLE dbo.Storage
(
ID INT NOT NULL PRIMARY KEY IDENTITY,
Description1 NVARCHAR(100) NULL,
Description2 NVARCHAR(100) NULL,
AddedBy NVARCHAR(50) NOT NULL
)
--------------------------------------------------
CREATE TABLE dbo.StoragePlace
(
ID INT NOT NULL PRIMARY KEY,
ID_PlantArea INT NOT NULL,
CONSTRAINT FK_StoragePlace_to_Storage FOREIGN KEY (ID) REFERENCES Storage(ID) ON DELETE CASCADE,
CONSTRAINT FK_StoragePlace_to_PlantArea FOREIGN KEY (ID_PlantArea) REFERENCES PlantArea(ID) ON DELETE CASCADE
)
My thought was, that UQX_Storage would trigger EF6 to accept a 1:0..1 relationship between Haul and Storage. Certainly, this doesn't work; it still insists on a 1:* relationship, which, from my understanding, shall not be possible with this model above.
How can I enforce the intended 1:0..1 relationship between Haul and Storage?
EDIT:
I just realized, that the ID_Storage field can never be NULL, so I replaced the UQX_Storage "constraint" with a simple ID_Storage INT NOT NULL UNIQUE,. However, that didn't solve the problem either.

SQL Server : two foreign keys pointing to one table. Error: Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths

I'm getting the error:
Msg 1785, Level 16, State 0, Line 238
Introducing FOREIGN KEY constraint 'FK_Studios_Members_HeadId' on table 'Studios' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Below is a simplified version of the two tables I'm having problems with:
CREATE TABLE [Members]
(
[MemberId] int NOT NULL IDENTITY
)
CREATE TABLE [Studios]
(
[StudioId] int NOT NULL IDENTITY,
[HeadId] int,
[OwnerId] int,
CONSTRAINT [PK_Studios] PRIMARY KEY ([StudioId]),
CONSTRAINT [FK_Studios_Members_OwnerId]
FOREIGN KEY ([OwnerId]) REFERENCES [Members] ([MemberId])
ON DELETE SET NULL,
CONSTRAINT [FK_Studios_Members_HeadId]
FOREIGN KEY ([HeadId]) REFERENCES [Members] ([MemberId])
ON DELETE SET NULL
)
I found that if I switch the order of the two FK's, it will always error on the second one. I don't see why this will cause a cascading problem since both have the "ON DELETE SET NULL".
This is being generated by EF Core code-first, so I need the relationships and can't just hack in trigger in the backend.
What am I missing?
I'm not sure of an answer that will work with what you have there and I'm not sure how set in stone your design is...but as an alternate design that I don't think would have the same issue have you considered a separate middle relationship table?
One benefit of this approach is it allows you to have multiple members at each position.
CREATE TABLE [Members]
(
[MemberId] int NOT NULL IDENTITY
)
CREATE TABLE [Studios]
(
[StudioId] int NOT NULL IDENTITY,
CONSTRAINT [PK_Studios] PRIMARY KEY ([StudioId]),
)
--Contains Owner, Head, etc.
CREATE TABLE [Relationships]
(
[RelationshipId] int NOT NULL IDENTITY,
[RelationshipId] nvarchar(20) NOT NULL
)
CREATE TABLE [StudioMemberRelationships]
(
[StudioMemberRelationshipId] int NOT NULL IDENTITY,
[StudioId] int NOT NULL,
[MemberId] int NOT NULL,
[RelationshipTypeId] int NOT NULL,
CONSTRAINT [FK_StudioMemberRelationships_StudioId]
FOREIGN KEY ([StudioId]) REFERENCES [Studios] ([StudioId])
ON DELETE SET NULL,
CONSTRAINT [FK_StudioMemberRelationships_MemberId]
FOREIGN KEY ([MemberId]) REFERENCES [Members] ([MemberId])
ON DELETE SET NULL,
CONSTRAINT [FK_StudioMemberRelationships_RelationshipId]
FOREIGN KEY ([RelationshipId]) REFERENCES [Relationships] ([RelationshipId])
ON DELETE SET NULL
)

SQL Server Foreign Key references invalid Table 'employees'

I try to run this SQL Server query:
USE DB_UBB;
CREATE TABLE dept_emp (
emp_no INT NOT NULL,
dept_no CHAR(4) NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE, -- Error here
FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE, -- And here
PRIMARY KEY (emp_no, dept_no)
);
CREATE INDEX (emp_no);
CREATE INDEX (dept_no);
and I get these errors:
Foreign key 'FK__dept_emp__8bc6840bee39d6cef4bd' references invalid table 'employees'.
Foreign key 'fk__dept_emp__99bc0b2304d3f32059a9' references invalid table 'departments'.
even though I have these tables:
What do I do wrong?
EDIT:
Added Whole DB:
SQL ‘hides’ the columns from the Key of the Clustered Index in Nonclustered Indexes.
You have created a composite primary on both emp_no,dept_no
cluster index of primary will hide both columns from indexes in following queries and will generate error
CREATE INDEX (emp_no);
CREATE INDEX (dept_no);
If you are specifying the foreign key after the column specifications, try using the CONSTRAINT clause instead:
to_date DATE NOT NULL,
CONSTRAINT fk_dept_emp_dept FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE,
CONSTRAINT fk_dept_emp_emp FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE,
Aparently, I even though the tables were created, it didn't recognize them.
I added an <if not exist, create tables>
I also removed the CREATE INDEX (emp_no); and CREATE INDEX (dept_no); as #Muhammad Nasir said, but it didn't fix the referencing issue.
Solution:
USE DB_UBB;
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='employees' and xtype='U')
CREATE TABLE employees (
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender VARCHAR(1) NOT NULL CHECK (gender IN('M', 'F')),
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
);
GO
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='departments' and xtype='U')
CREATE TABLE departments (
dept_no CHAR(4) NOT NULL,
dept_name VARCHAR(40) NOT NULL,
PRIMARY KEY (dept_no),
UNIQUE (dept_name)
);
GO
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='dept_emp' and xtype='U')
CREATE TABLE dept_emp (
emp_no INT NOT NULL,
dept_no CHAR(4) NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, dept_no)
);
GO

Can't find where multiple cascade paths or cycles are in SQL Code?

I keep getting the following error
Msg 1785, Level 16, State 0, Line 99
Introducing FOREIGN KEY constraint 'FK_linkUserGroup_tblStudent' on table >'linkUserGroup' may cause cycles or multiple cascade paths. Specify ON DELETE ?>NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 0, Line 99
Could not create constraint or index. See previous errors.
I cannot understand how a cycle or multiple cascade paths are possible? I also cannot understand how a FK constraints to the TeacherID are not causing the same problem? My understanding is that should the parent StudentID be deleted then by specifying that On Delete No Action in the child table should ensure that the record is not deleted from the child table. I don't understand how their is any other path or possible cycle? Please help
CREATE TABLE tblUserAccount (
uaUserAccountID INT IDENTITY (1,1) CONSTRAINT PK_tblUserAccount PRIMARY KEY CLUSTERED,
uaUserAccountTitle NVARCHAR (50) NOT NULL,
uaUserAccountFirstName NVARCHAR (50) NOT NULL,
uaUserAccountSurname NVARCHAR (50) NOT NULL,
uaUserAccountUserName NVARCHAR (50) NOT NULL,
uaUserAccountPassword NVARCHAR (50) NOT NULL,
uaDateTimeModified DATETIME
CONSTRAINT DF_tblUserAccount_DateTimeModified DEFAULT SYSDATETIME()
);
CREATE TABLE tblRole (
rRoleID INT IDENTITY (1, 1) CONSTRAINT PK_tblRole PRIMARY KEY CLUSTERED,
rRole NVARCHAR (50),
rRoleDescription NVARCHAR (MAX) NULL,
rDateTimeModified DATETIME
CONSTRAINT DF_tblRole_DateTimeModified DEFAULT SYSDATETIME()
);
CREATE TABLE linkUserAccountRole (
uarUserAccountID INT,
uarRoleID INT,
uarDateTimeModified DATETIME
CONSTRAINT DF_linkUserAccountRole_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT PK_linkUserAcccountRole
PRIMARY KEY CLUSTERED (uarUserAccountID , uarRoleID)
,CONSTRAINT FK_linkUserAcccountRole_tblRole
FOREIGN KEY (uarRoleID)
REFERENCES tblRole (rRoleID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserAcccountRole_tblUserAccount
FOREIGN KEY (uarUserAccountID)
REFERENCES tblUserAccount (uaUserAccountID)
ON DELETE NO ACTION
ON UPDATE CASCADE
);
CREATE TABLE tblTeacher (
tTeacherID INT CONSTRAINT PK_tblTeacher PRIMARY KEY CLUSTERED,
tUserAccountID INT,
tDateTimeModified DATETIME
CONSTRAINT DF_tblTeacher_DateTimeModified DEFAULT SYSDATETIME(),
CONSTRAINT FK_tblTeacher_tblUserAccount
FOREIGN KEY (tUserAccountID)
REFERENCES tblUserAccount(uaUserAccountID)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE tblStudent (
sStudentID INT CONSTRAINT PK_tblStudent PRIMARY KEY CLUSTERED,
sUserAccountID INT,
sDateTimeModified DATETIME
CONSTRAINT DF_tblStudent_DateTimeModified DEFAULT SYSDATETIME(),
CONSTRAINT FK_tblStudent_tblUserAccount
FOREIGN KEY (sUserAccountID)
REFERENCES tblUserAccount(uaUserAccountID)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE tblKeyStage (
ksKeyStageGroupID INT IDENTITY (1,1) CONSTRAINT PK_tblKeyStage PRIMARY KEY CLUSTERED,
ksKeyStageTitle NVARCHAR (50) NOT NULL,
ksKeyStageDescription NVARCHAR(50),
ksDateTimeModified DATETIME
CONSTRAINT DF_tblKeyStage_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT UQ_tblKeyStage_KeyStageTitle UNIQUE (ksKeyStageTitle)
);
CREATE TABLE tblYearGroup (
ygYearGroupID INT IDENTITY (1,1) CONSTRAINT PK_tblYearGroup PRIMARY KEY CLUSTERED,
ygYearGroupTitle NVARCHAR (50) NOT NULL,
ygYearGroupDescription NVARCHAR(50),
ygDateTimeModified DATETIME
CONSTRAINT DF_tblYearGroup_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT UQ_tblYearGroup_YearGroupTitle UNIQUE (ygYearGroupTitle)
);
CREATE TABLE tblClassGroup (
cgClassGroupID INT IDENTITY (1,1) CONSTRAINT PK_tblClassGroup PRIMARY KEY CLUSTERED,
cgClassGroupTitle NVARCHAR (50) NOT NULL,
cgClassGroupDescription NVARCHAR (50),
cgDateTimeModified DATETIME
CONSTRAINT DF_tblClassGroup_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT UQ_tblClassGroup_ClassGroupTitle UNIQUE (cgClassGroupTitle)
);
CREATE TABLE tblLearningGroup (
lgLearningGroupID INT IDENTITY (1,1) CONSTRAINT PK_tblLearningGroup PRIMARY KEY CLUSTERED,
lgLearningGroupTitle NVARCHAR (50) NOT NULL,
lgLearningGroupDescription NVARCHAR (50),
lgDateTimeModified DATETIME
CONSTRAINT DF_tblLearningGroup_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT UQ_tblLearningGroup_LearningGroupTitle UNIQUE (lgLearningGroupTitle)
);
CREATE TABLE tblLearningGroup (
lgLearningGroupID INT IDENTITY (1,1) CONSTRAINT PK_tblLearningGroup PRIMARY KEY CLUSTERED,
lgLearningGroupTitle NVARCHAR (50) NOT NULL,
lgLearningGroupDescription NVARCHAR (50),
lgDateTimeModified DATETIME
CONSTRAINT DF_tblLearningGroup_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT UQ_tblLearningGroup_LearningGroupTitle UNIQUE (lgLearningGroupTitle)
);
CREATE TABLE linkUserGroup (
ugTeacherID INT,
ugStudentID INT,
ugKeyStageGroupID INT,
ugYearGroupID INT,
ugClassGroupID INT,
ugLearningGroupID INT,
ugDateTimeModified DATETIME
CONSTRAINT DF_linkUserGroup_DateTimeModified DEFAULT SYSDATETIME()
,CONSTRAINT PK_linkUserGroup
PRIMARY KEY CLUSTERED (ugTeacherID, ugStudentID, ugClassGroupID, ugLearningGroupID)
,CONSTRAINT FK_linkUserGroup_tblTeacher
FOREIGN KEY (ugTeacherID)
REFERENCES tblTeacher (tTeacherID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserGroup_tblStudent
FOREIGN KEY (ugStudentID)
REFERENCES tblStudent (sStudentID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserGroup_tblKeyStage
FOREIGN KEY (ugKeyStageGroupID)
REFERENCES tblKeyStage (ksKeyStageGroupID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserGroup_tblYearGroup
FOREIGN KEY (ugYearGroupID)
REFERENCES tblYearGroup (ygYearGroupID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserGroup_tblClassGroup
FOREIGN KEY (ugClassGroupID)
REFERENCES tblClassGroup (cgClassGroupID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT FK_linkUserGroup_tblLearningGroup
FOREIGN KEY (ugLearningGroupID)
REFERENCES tblLearningGroup (lgLearningGroupID)
ON DELETE NO ACTION
ON UPDATE CASCADE
,CONSTRAINT UQ_linkUserGroup_PK_YearGroupID
UNIQUE (ugTeacherID, ugStudentID, ugClassGroupID, ugLearningGroupID, ugYearGroupID)
);
Multiple cascade paths exist between tblUserAccount and linkUserGroup:
tblUserAccount -> tblTeacher -> linkUserGroup
tblUserAccount -> tblStudent -> linkUserGroup
It is not the FK constraint itself which is not allowed, but the action: ON UPDATE CASCADE.
You can either specify ON UPDATE CASCADE for FK_linkUserGroup_tblTeacher, or ON UPDATE CASCADE for FK_linkUserGroup_tblStudent, but not for both.
Your ON DELETE is already marked as NO ACTION, so it is fine. It is ON UPDATE which you should decide what to do.
There are 2 options:
1) Forbid updating the key which participates in a FK constraint.
To do that specify ON UPDATE NO ACTION, or just remove the ON UPDATE clause altogether, because this is the default behaviour of a foreign key constraint.
Considering that updating a primary key is usually not a good idea (whether it is referenced by a foreign key or not), I would recommend this option.
2) If automatic propagation of changed sStudentID and tTeacherID to linkUserGroup is really what you want, then you can use triggers.

Resources