There are apparently 2 problems with you constraint:
- Msg 1046, Level 15, State 1, Line 244 Subqueries are not allowed in this context. Only scalar expressions are allowed.
What this means is that you can not use a subquery inside a check constraint, you can only validate such constraint row by row. Examples of valid check constraints would be:
CHECK ( x BETWEEN 1 AND 3 )
CHECK ( x > y )
I think sub-queries are allowed according to SQL-standard, but few if any vendors allow it. Apparently SQL-server is not among those that do.
so the culprit for this problem is:
AND REFmusic = ( select IDmusic FROM Catalogue Where censure = 'YES' )
Let's remove that part and try:
ALTER TABLE Historique_ecoute ADD CONSTRAINT majorite_utilisateur
CHECK (not (DATEDIFF(yyyy, Utilisateurs.Date_naissance, GETDATE()) < 18)
My guess is that this is not allowed either, because GETDATE() is not deterministic, so a row may be valid during insert but invalid a little bit later. A constraint is never allowed to evaluate to False. During a modification of a row, the constraints can be validated, but in your case, the truth value of the constraint can change without any modification being made. What action would be taken when the constraint all the sudden evaluates to False? There is no transaction that can be rolled backed, no user that can be notified.
As a side-note, I don't understand what Utilisateurs.Date_naissance refers to?
- Msg 4104, Level 16, State 1, Line 255 The multi-part identifier "Catalogue.annee" could not be bound.
This error I don't understand. I can't locate annee anywhere in the constraint.
I assume that the choice of song is written to some table ( Historique_ecoute ). What you can do is create a trigger that validates the condition
CREATE TRIGGER validate_age ON Historique_ecoute
AFTER INSERT
AS
IF (DATEDIFF(yyyy, Utilisateurs.Date_naissance, GETDATE()) < 18)
RAISERROR ('You are not allowed to ...',
ROLLBACK TRANSACTION;
END;
I don't know the exact syntax, but you should get the idea. I did copy the trigger stuff from CREATE TRIGGER
SELECT
statement within theWHERE
clause. If the RDBMS supports RLS (Row Level Security), that would be my recommended method. If not, hide the logic within aVIEW
.