Hello,
Je rencontre des problèmes pour établir une contrainte CHECK. Lorsque j'exécute l'ordre ALTER TABLE pour l'ajouter, j'ai un message d'erreur disant que l'ordre entre en conflit avec la contrainte que je tente d'ajouter.
Le contexte :
J'ai les tables suivantes (je les ai édulcorées pour ne garder que les colonnes servant dans les clefs ou contraintes histoire d'alléger un peu) :
On a donc une première table qui contient le "header" des promos. Juste un nom et des dates de début et de fin.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 --contient la liste des promo CREATE TABLE [S_PROMO].[T_PROMO_PRM]( [PRM_ID] [int] IDENTITY(-2147483648,1) NOT NULL, [PRM_STARTDATE] [date] NOT NULL, [PRM_ENDDATE] [date] NOT NULL, [PRM_STARTTIME] [time](0) NOT NULL, [PRM_ENDTIME] [time](0) NOT NULL, [PRM_DESC] [varchar](50) NOT NULL, [PRT_ID] [tinyint] NOT NULL, CONSTRAINT [PK_T_PROMO_PRM] PRIMARY KEY CLUSTERED ( [PRM_ID] ASC ) ) ON [PRIMARY] --contient le détail des promos pour la marchandise propre CREATE TABLE [S_PROMO].[T_DETAIL_OWN_DTO]( [DTO_ID] [int] IDENTITY(-2147483648,1) NOT NULL, [PRM_ID] [int] NOT NULL, [DEP_ID] [smallint] NOT NULL, [BRA_ID] [int] NOT NULL, [DTO_PERCENT] [decimal](4, 2) NOT NULL, [PCT_ID] [tinyint] NOT NULL, CONSTRAINT [PK_T_DETAIL_OWN_DTO] PRIMARY KEY CLUSTERED ( [DTO_ID] ASC ), CONSTRAINT [AK_T_DETAIL_OWN_DTO] UNIQUE NONCLUSTERED ( [PRM_ID] ASC, [DEP_ID] ASC, [BRA_ID] ASC, [DTO_PERCENT] ASC, [PCT_ID] ASC ) ) ON [PRIMARY] GO ALTER TABLE [S_PROMO].[T_DETAIL_OWN_DTO] WITH CHECK ADD CONSTRAINT [FK_DTO_TO_PRM] FOREIGN KEY([PRM_ID]) REFERENCES [S_PROMO].[T_PROMO_PRM] ([PRM_ID]) GO --contient les listes d'articles en promo CREATE TABLE [S_PROMO].[T_PRODUCT_LIST_OWN_PLO]( [DTO_ID] [int] NOT NULL, [PLO_BARCODE] [char](13) NOT NULL, [PLO_INCLUSIVE] [bit] NOT NULL, CONSTRAINT [PK_T_PRODUCT_LIST_OWN_PLO] PRIMARY KEY CLUSTERED ( [DTO_ID] ASC, [PLO_BARCODE] ASC ) ) ON [PRIMARY] ALTER TABLE [S_PROMO].[T_PRODUCT_LIST_OWN_PLO] WITH CHECK ADD CONSTRAINT [FK_PLO_TO_DTO] FOREIGN KEY([DTO_ID]) REFERENCES [S_PROMO].[T_DETAIL_OWN_DTO] ([DTO_ID]) ON DELETE CASCADE GO
La deuxième table indique sur quelle marque (BRA_ID), dans quel rayon (DEP_ID) il y a une promo et quel est le pourcentage de cette promo (DTO_PERCENT).*
La dernière table indique les articles qui sont concernés par la promo de la 2e table (seulement si PCT_ID indique qu'il s'agit d'une liste)
* PCT_ID indique le type de pourcentage, cela peut-être automatique (cad sur tous les articles de la marque dans le rayon) ou sur seulement sur une liste d'articles.
La contrainte :
Le but de la contrainte est d'empêcher qu'un article se retrouve dans deux listes sous une même promo.
J'ai donc écrit la fonction suivante :
Et l'ordre de modification e table qui va avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 CREATE FUNCTION S_PROMO.UF_CHECK_DOUBLE_EAN_OWN (@BARCODE CHAR(13), @DTO_ID INT) RETURNS BIT AS BEGIN DECLARE @RESULT BIT; DECLARE @COUNT INT; DECLARE @PRM_ID INT; SELECT @PRM_ID = PRM_ID FROM S_PROMO.T_DETAIL_OWN_DTO WHERE DTO_ID = @DTO_ID; SELECT @COUNT = COUNT(*) FROM S_PROMO.T_PRODUCT_LIST_OWN_PLO PLO INNER JOIN S_PROMO.T_DETAIL_OWN_DTO DTO ON PLO.DTO_ID = DTO.DTO_ID WHERE DTO.PRM_ID = @PRM_ID AND PLO.PLO_BARCODE = @BARCODE; IF @COUNT = 1 SET @RESULT = 0 ELSE SET @RESULT = 1 RETURN @RESULT; END
Et j'ai donc le message suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part ALTER TABLE S_PROMO.T_PRODUCT_LIST_OWN_PLO ADD CONSTRAINT CK_DOUBLE_PROMO CHECK (S_PROMO.UF_CHECK_DOUBLE_EAN_OWN(PLO_BARCODE, DTO_ID)=0);
Mes tests :Msg 547, Level 16, State 0, Line 2
The ALTER TABLE statement conflicted with the CHECK constraint "CK_DOUBLE_PROMO". The conflict occurred in database "INNO_ADMIN", table "S_PROMO.T_PRODUCT_LIST_OWN_PLO".
Avant d'écrire le code ci-dessus pour établir cette contrainte, j'avais testé comme ceci :
Avec ce code, si je fais INSERT INTO S_TEST.T_TEST_TST(TST_CODE) VALUES ('1234'), l'insertion se fait bien la 1e fois mais pas les fois suivantes. Cela assure donc bien qu'il n'y ai qu'une ligne avec un code.**
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 CREATE SCHEMA S_TEST; GO CREATE TABLE S_TEST.T_TEST_TST( TST_ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY, TST_CODE CHAR(4) NOT NULL) GO CREATE FUNCTION S_TEST.UF_CHECK_DOUBLE_CODE(@CODE CHAR(4)) RETURNS BIT AS BEGIN DECLARE @RESULT BIT; DECLARE @COUNT INT; SELECT @COUNT = COUNT(*) FROM S_TEST.T_TEST_TST WHERE TST_CODE = @CODE IF @COUNT = 1 SET @RESULT = 0 ELSE SET @RESULT = 1 RETURN @RESULT; END GO ALTER TABLE S_TEST.T_TEST_TST WITH CHECK ADD CONSTRAINT CK_DOUBLE_CODE CHECK (S_TEST.UF_CHECK_DOUBLE_CODE(TST_CODE)=0);
** Ici j'aurai pu me contenter d'ajouter un index unique sur la colonne TST_CODE mais vu que dans le cas concret, je dois faire référence à une autre table, j'ai directement tester en écrivant une fonction.
En conclusion :
Quelqu'un pourrait-il m'aiguiller sur ce que je fais de travers ??
J'ai bien sûr vérifier et il n'y a pas de barcode en double pour une même promo dans la table concerné par la contrainte. Du coup, je reste perplexe sur le pourquoi de ce message d'erreur. J'imagine bien qu'il doit y avoir une faille dans ma fonction mais je ne vois pas où .
Merci d'avance à ceux qui prendront la peine de lire ce pavé.
Partager