Je voudrais créer une table avec la contrainte CHECK, où CHECK appelle une fonction scalaire définie par l'user. J'ai lu sur plusieurs sites que c'est possible, aussi qu'il a de mauvaises performances. Même si je voudrais le faire.
J'ai cette table
CREATE TABLE [book_history] ( id int NOT NULL IDENTITY PRIMARY KEY, user_id int NOT NULL, library_id int NOT NULL, book_id int NOT NULL, borrow_time datetime DEFAULT GETDATE(), return_policy datetime DEFAULT DATEADD(DAY, 30, GETDATE()), return_time datetime, CHECK (dbo.fn_check_duplicate(user_id, library_id, book_id) = 0) );
et fonction
DROP FUNCTION IF EXISTS fn_check_duplicate GO CREATE FUNCTION fn_check_duplicate (@user_id int, @library_id int, @book_id int) RETURNS int BEGIN RETURN (SELECT COUNT(*) FROM [book_history] WHERE user_id = @user_id AND library_id = @library_id AND book_id = @book_id AND return_time IS NULL) END GO
Lorsque j'essaie d'insert une nouvelle ligne dans cette table book_history
(qui est vide), j'obtiens une erreur indiquant que l' The INSERT statement conflicted with the CHECK constraint "CK__book_history__267ABA7A". The conflict occurred in database "library", table "dbo.book_history".
The INSERT statement conflicted with the CHECK constraint "CK__book_history__267ABA7A". The conflict occurred in database "library", table "dbo.book_history".
COUNT est supposé renvoyer un type de données int basé sur la documentation MSDN.
Je suis propriétaire des deux, de la table et de la fonction.
Quelqu'un peut-il me dire ce que je fais mal?
Changez-le pour check (dbo.fn_check_duplicate(user_id, library_id, book_id) = 1)
La check
va regarder l'état de la table après l'insertion, donc vous voulez que le count soit 1.
Testez-le sur rextester: http://rextester.com/AWDNP40594 en décommentant la seconde insertion.
Vous pouvez également replace cette contrainte de vérification lente par un index unique filtré comme suit:
create unique nonclustered index uix_book_history_user_library_book on dbo.book_history (user_id, library_id, book_id) where return_time is null
Cela pourrait être plus de ce que vous essayez de faire, si chaque book_id est un livre individuel:
create unique nonclustered index uix_book_history_library_book on dbo.book_history (library_id, book_id) where return_time is null
Parce que cela permettrait à un livre d'être extrait seulement par un user à la fois.