I have a database where there's one base table that is extended (by foreign keying) by other tables. Something like this:
I've been assigned a task where I have to do the following check before inserting an "Animal":
- Animals Id must be UNIQUE
- (Thus) Fishes Id must be UNIQUE
- There may be ZERO OR MORE "dead" (Alive = False) Fishes for a specific FishEspecieId
- There may be ZERO OR ONE "alive" (Alive = True) Fish for a specific FishEspecieId
The task suggested that I do it on API insert method, something like this (pseudo-code):
Method Insert(Fish fish)
Fish[] fishes = DB.GetAll<Fish>()
if (fishes.Any(f => f.FishEspecieId == fish.FishEspecieId f.Animal.Alive))
throw "Only one alive fish allowed"
Animal animal = DB.Insert<Animal>({alive: true})
DB.Insert({Id: animal.Id, ...})
I'm actually going to, indeed, do a check in the API. However, I think it's a good idea to also ensure the rules on the DB side.
How may I do this in SQL Server? And is this indeed a good idea or should I keep only in the backend side?
Ps. This is only a MRE. I know that if this was my database I should make it a single table. If that was the case, I would simply use UNIQUE(FishEspecieId) WHERE (Alive = 1)
. In my case, however, I have many tables that extends "Animal", or something like this.
UNIQUE (FishEspecieId, Id) WHERE (Alive = 1)
. What is the datatype of columnAlive
?Fish.ID
aForeign Key
toAnimal.ID
?Animal.Id
.UNIQUE(Fish.FishEspecieId) WHERE (Animal.Alive = 1)
, when inserting a Animal. Of course I can't use UNIQUE with multiple tables, but this is the idea. Example: I have a Fish with FishEspecieId of 1. I may only insert an Animal that will in the future have a Fish associetade with it and has FishEspecieId of 1 if this first Fish is related with an Animal that is not Alive. If it's Alive, the UNIQUE constraint fails.