Question

CREATE TABLE [dbo].[ProjectTasks]
(
    [TaskID] [int] IDENTITY(1,1) NOT NULL,
    ...
    [DefaultTaskValue] [int] NULL
)

ALTER TABLE [dbo].[ProjectTasks] ADD  CONSTRAINT [PK_ProjectTasks] PRIMARY KEY 
CLUSTERED 
(
    [TaskID] ASC
)

ALTER TABLE [dbo].[ProjectTasks] ADD CONSTRAINT [FK_ProjectTasks_TaskValues] 
FOREIGN KEY([TaskID], [DefaultTaskValue])
REFERENCES [dbo].[TaskValues] ([TaskID], [Value])
GO

CREATE TABLE [dbo].[TaskValues]
(
    [TaskID] [int] NOT NULL,
    [Value] [int] NOT NULL,
    ...
)

ALTER TABLE [dbo].[TaskValues] ADD  CONSTRAINT [PK_TaskValues] PRIMARY KEY CLUSTERED 
(
    [TaskID] ASC,
    [Value] ASC
)

ALTER TABLE [dbo].[TaskValues] ADD CONSTRAINT [FK_TaskValues_ProjectTasks] 
FOREIGN KEY([TaskID])
REFERENCES [dbo].[ProjectTasks] ([TaskID])
GO

Given the above, no record in either table can be deleted - is there any neat solution? What I'd LIKE to do is sort the design to make the link table a pure link table and not to itself carry the value. This has not been a problem up to now because rows were never required to be actually deleted (they were flagged, but not actually deleted), and of course you can insert because DefaultValue can be NULL.

EDIT: In response to my downmarker, I should have mentioned, I have considered both ON DELETE CASCADE and a TRIGGER, I am looking for alternatives to those scenarios, and clearly ON DELETE SET NULL will not work.

Was it helpful?

Solution

I was surprised by your statement

and of course you can insert because DefaultValue can be NULL

and had to look it up. MSKB says

Specifically, if a composite foreign key has been defined on columns that allow nulls, and at least one of the columns, upon the insert or update of a row, is set to null, then the foreign key constraint will be satisfied. This is true even if there is not a row in the related table to which any of the corresponding columns are matched.

I guess I was not aware of this information. So I suggest the following commands:

UPDATE ProjectTasks SET DefaultTaskValue = NULL *W
DELETE TaskValues *W
DELETE ProjectTasks *W

*W is your WHERE condition (on TaskID etc)

OTHER TIPS

One solution is to remove the DefaultTaskValue column and create another DefaultTaskvalues table. This way, all columns can be set as NOT NULL and cascading effects as you please.

ProjectTasks table:

CREATE TABLE [dbo].[ProjectTasks]
(
    [TaskID] [int] IDENTITY(1,1) NOT NULL,
    ...
                         --- removed: DefaultTaskValue] [int] NULL
)

ALTER TABLE [dbo].[ProjectTasks] 
  ADD CONSTRAINT [PK_ProjectTasks] 
  PRIMARY KEY CLUSTERED 
(
    [TaskID] ASC
)
GO

TaskValues table:

CREATE TABLE [dbo].[TaskValues]
(
    [TaskID] [int] NOT NULL,
    [Value] [int] NOT NULL,
    ...
)

ALTER TABLE [dbo].[TaskValues] 
  ADD CONSTRAINT [PK_TaskValues] 
  PRIMARY KEY CLUSTERED 
(
    [TaskID] ASC,
    [Value] ASC
)

ALTER TABLE [dbo].[TaskValues]
  ADD CONSTRAINT [FK_TaskValues_ProjectTasks] 
  FOREIGN KEY([TaskID])
  REFERENCES [dbo].[ProjectTasks] ([TaskID])
GO

DefaultTaskValues table:

CREATE TABLE [dbo].[DefaultTaskValues]
(
    [TaskID] [int] NOT NULL,
    [Value] [int] NOT NULL,
    ...
)

ALTER TABLE [dbo].[DefaultTaskValues] 
  ADD CONSTRAINT [PK_DefaultTaskValues] 
  PRIMARY KEY CLUSTERED 
(
    [TaskID] ASC
)

ALTER TABLE [dbo].[DefaultTaskValues] 
  ADD CONSTRAINT [FK_DefaultTaskValues_TaskValues] 
  FOREIGN KEY([TaskID], [Value])
  REFERENCES [dbo].[TaskValues] ([TaskID], [Value])
GO
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top