Pour plus de détails sur CREATE ASSERTION
voir la spécification ISO standard SQL-92. La définition de CHECK
devrait être entre parenthèses.
CURRENT_DATE
n'a pas de parenthèses.
USER
et DATE
sont des mots réservés.
Les instructions SQL doivent être terminées par un point-virgule.
Les mots-clés SQL doivent être en majuscules.
Essayez quelque chose comme ceci:
CREATE ASSERTION assert
CHECK (0 = (
SELECT COUNT(*)
FROM Video
WHERE my_date = CURRENT_DATE
GROUP
BY my_user
HAVING COUNT(*) >= 10
));
Vous pouvez tester que la syntaxe est correcte à l'aide du Mimer en ligne SQL-92 Validator. Cependant, vous devriez également tester votre logique, par ex. CURRENT_DATE
est non déterministe.
En outre, je ne pense pas que ASSERTION
mordra jamais. Lorsque la cardinalité de la sous-requête est inférieure à 10, elle renvoie zéro ligne et 0 = empty set
est évaluée à UNKNOWN
. Lorsque la cardinalité de la sous-requête est égale ou supérieure à 10, la condition de recherche évalue TRUE
. SQL-92 états standard
L'affirmation n'est pas satisfaite si et que si le résultat de l'évaluation de la condition de recherche est fausse.
Notez que vous pouvez remplacer votre CHECK (0 = (SELECT COUNT(*) FROM...))
construction avec CHECK (NOT EXISTS (SELECT * FROM...))
, ce dernier dont je trouve plus facile à écrire.
MISE À JOUR:
Comment dois-je écrire l'affirmation à l'aide CHÈQUE EXISTE PAS?
Comme je l'ai dit ci-dessus, votre logique semble erronée de sorte qu'il est difficile de mettre en œuvre correctement;)
Disons que la règle est de limiter les vidéos à 10 par utilisateur et par jour.Parce que cela implique seulement une seule table, il serait plus approprié d'utiliser une contrainte CHECK
au niveau de la table; une telle contrainte est vérifiée quand la table est mise à jour ce qui est suffisant dans ce cas (il n'y a pas de raison pour que cela ne soit pas un ASSERTION
, qui peut être vérifié en théorie chaque fois que une table dans le schéma est mise à jour):
ALTER TABLE Video ADD
CONSTRAINT video_limit_10_per_user_per_day
CHECK (NOT EXISTS (
SELECT v1.my_user, v1.my_date
FROM Video AS V1
GROUP BY v1.my_user, v1.my_date
HAVING COUNT(*) > 10
));
MISE à JOUR 2:
merci, maintenant, disons que nous voulons limiter vidéos à 100 par utilisateur et par an, dans ce cas en utilisant current_date serait nécessaire ne serait-il pas?
réexaminera qu'un CHECK
/ASSERTION
ne sera vérifié lorsque les données dans le tableau/schéma est mis à jour. Le problème avec l'utilisation de CURRENT_DATE
(et d'autres fonctions non déterministes) dans une contrainte est que la règle métier peut être invalidée simplement par l'horloge qui passe d'une période à l'autre mais si les données n'ont pas été changées dans cette période l'échec de l'intégrité des données ne sera pas détecté et la base de données contiendra des données non valides.
Une autre considération est ce que l'on entend par une année en contexte. Il peut s'agir de l'année calendaire (du 1er janvier au 31 décembre inclusivement) ou d'autres dates fixes définies par l'entreprise (par exemple du 1er avril au 31 mars inclus), auquel cas le regroupement par année et par utilisateur est trivial.
Un cas plus intéressant est lorsque la règle limite le décompte pour période de 12 mois; l'étendre à la fois au passé et au futur évite la question «non déterministe» ci-dessus. Considérons un standard approach of using an auxiliary calendar table, contenant une ligne pour chaque jour applicable à l'entreprise, étendu dans le passé et à l'avenir seulement pour autant que nécessaire ne devrait toujours comprendre que quelques milliers de lignes. Chaque ligne aurait la date comme une clé avec une deuxième colonne pour cette date plus un an (et si nécessaire, vous pourriez affiner la définition de 'une année' à une granularité d'un jour!) Le test pour impliquerait de rejoindre le calendrier tableau, regroupant sur la date du calendrier et l'utilisateur et en comptant par exemple quelque chose comme ceci:
SELECT C1.dt, V1.my_user
FROM Video AS V1
INNER JOIN Calendar AS C1
ON (V1.my_date BETWEEN C1.dt AND C1.dt_plus_one_year)
GROUP
BY C1.dt, V1.my_user
HAVING COUNT(*) > 100;
Cela pourrait être mis dans une contrainte CHECK (NOT EXISTS (...
. Cela pourrait toujours être une contrainte au niveau de la table: car la table Calendar est une table auxiliaire, elle ne serait sujette qu'à des mises à jour contrôlées peu fréquentes (mais peut également être un ASSERTION
si nécessaire).
La deuxième contrainte ne fonctionne-t-elle pas? Ou demandez-vous s'il y a un meilleur moyen? –
Je demande si c'est la bonne ou pas – user591931