Pb table auditable

jeanBap
Invité n'ayant pas de compte PHPfrance

10 mars 2010, 21:23

Bonjour,

Je suis en train de faire une base sous MySQL: 5.0.32.
J'aimerai avoir 2 tables auditables.

reportage représente les reportage photo dont la cle est Id, Audit_Version et Audit_Current (je ne voudrais que les versions courantes dans cette table).
reportage_HIST est l'historique de reportage (je veux la version courante de chaque reportage et chaque version antérieure).

Les tables se créent bien via mysql et j'ai tenté de remplir avec 1 tuple la table reportage (via le formulaire de mysql). J'ai été surpris de constater que reportage_HIST est restée vide... Vu la contrainte entre les 2, je ne comprends pas.



CREATE TABLE Reportage (
						Id INT NOT NULL AUTO_INCREMENT,
						Name VARCHAR(25) NOT NULL,
						Audit_Current VARCHAR(1) NOT NULL DEFAULT 'Y',
						Audit_DateTime DATETIME NOT NULL,
						Audit_User VARCHAR(25) NOT NULL,
						Audit_Version INT NOT NULL DEFAULT 1,
						Audit_Status ENUM('DONE','VER','PENDING SAVE','PENDING CANCEL','CANCEL'),
						Audit_Action ENUM ('SAVE','ACCEPT','DO','CANCEL','REJECT'),
						PRIMARY KEY(Id, Audit_Current, Audit_Version)) TYPE=INNODB;

CREATE TABLE Reportage_HIST (
						Id INT NOT NULL AUTO_INCREMENT,
						Name VARCHAR(25) NOT NULL,
						Audit_Current ENUM('Y','N'),
						Audit_DateTime DATETIME NOT NULL,
						Audit_User VARCHAR(25) NOT NULL,
						Audit_Version INT NOT NULL DEFAULT 1,
						Audit_Status  ENUM('DONE','VER','PENDING SAVE','PENDING CANCEL','CANCEL'),
						Audit_Action ENUM ('SAVE','ACCEPT','DO','CANCEL','REJECT'),
						PRIMARY KEY(Id, Audit_Current, Audit_Version),
						FOREIGN KEY (Id, Audit_Current, Audit_Version)
							REFERENCES Reportage(Id, Audit_Current, Audit_Version)
							ON UPDATE CASCADE ON DELETE RESTRICT
						
						) TYPE=INNODB;



ps:J'ai essayé avec
	FOREIGN KEY (Id, Audit_Current, Audit_Version)
							REFERENCES Reportage(Id, Audit_Current, Audit_Version)
							ON UPDATE CASCADE ON DELETE CASCADE ON INSERT RESTRICT
mais j'ai un beau message d'erreur.

Est ce que je vais devoir à chaque insert dans reportage faire son homologue dans reportage_hist? N y a t il pas un moyen que le sgbd se débrouille tout seul?
Merci

Eléphanteau du PHP | 31 Messages

10 mars 2010, 22:58

Bonjour,


Dans ta première table tu as :
Audit_Current VARCHAR(1) NOT NULL DEFAULT 'Y' 
Dans la seconde :
Audit_Current ENUM('Y','N')
Ta clé étrangère se base sur le champ Audit_Current. Les deux champs n'ont pas le même type, tu ne devrais même pas pouvoir créer les tables. Tu peux essayer en corrigeant ça.

jeanBap
Invité n'ayant pas de compte PHPfrance

10 mars 2010, 23:43

Oui ce n'était pas les bonnes requêtes, en fait, dans reportage, il n'y aura que des valeurs 'Y' et dans reportage_HIST il y aura 'Y' et 'N', j'ai donc supprimé de mes deux tables le type enum.

Je ne suis pas un expert de MySql mais d'après ce que j'ai vu la contrainte ON DELETE CASCADE ON UPDATE CASCADE dit que si j'efface ou je mets à jour un tuple de reportage cela fera la même action dans reportage_HIST grâce aux valeurs de la clé étrangère référencées dans reportage.

Je n'ai rien vu pour une option de type INSERT, cela ne doit pas exister...

Je vais devoir m'appliquer dans mes requêtes d'insertion...

sauf si vous connaissez un moyen.

Merci

Eléphanteau du PHP | 13 Messages

14 mars 2010, 16:05

salut,

voici mes tables

CREATE TABLE Reportage (
						Id INT AUTO_INCREMENT,
						Name VARCHAR(25) NOT NULL,
						Audit_Current ENUM('Y','N'),
						Audit_DateTime DATETIME NOT NULL,
						Audit_User VARCHAR(25) NOT NULL,
						Audit_Version INT DEFAULT 1,
						Audit_Status ENUM('DONE','PUBLISH','DISABLE'),
						Audit_Action ENUM ('DO','PUBLISHED', 'SAVE','DISABLED','REJECT'),
						PRIMARY KEY(Id, Audit_Current, Audit_Version)) TYPE=INNODB;

CREATE TABLE Reportage_HIST (
						Id INT  AUTO_INCREMENT,
						Name VARCHAR(25) NOT NULL,
						Audit_Current ENUM('Y','N'),
						Audit_DateTime DATETIME NOT NULL,
						Audit_User VARCHAR(25) NOT NULL,
						Audit_Version INT  DEFAULT 1,
						Audit_Status ENUM('DONE','PUBLISH','DISABLE'),
						Audit_Action ENUM ('DO','PUBLISHED', 'SAVE','DISABLED','REJECT'),
						PRIMARY KEY(Id, Audit_Current, Audit_Version),
						INDEX rep_ind (Id, Audit_Current,Audit_Version),
						FOREIGN KEY (Id, Audit_Current, Audit_Version)
							REFERENCES Reportage(Id, Audit_Current, Audit_Version)
							ON UPDATE CASCADE ON DELETE SET NULL
						
						) TYPE=INNODB;
pour permettre de faire des updates en cascade et des suppressions dans Reportage sans toucher à Reportage_HIST.
Par contre:
impossible de créer Reportage_HIST (je suis obligé de retirer TYPE=INNODB) et par conséquent, un update dans Reportage ne se reporte pas dans Reportage_HIST. En revanche, le delete fonctionne très bien.

Savez vous ce que je dois faire?
Merci.

Eléphanteau du PHP | 13 Messages

17 mars 2010, 02:02

là aussi, j'ai trouvé en cherchant..en gros ma dernière version de table est moche. Je vous la remets.

CREATE TABLE Reportage (
                                                Id INT AUTO_INCREMENT,
                                                Name VARCHAR(25) NOT NULL,
                                                Audit_Current ENUM('Y','N'),
                                                Audit_DateTime DATETIME NOT NULL,
                                                Audit_User VARCHAR(25) NOT NULL,
                                                Audit_Version INT DEFAULT 1,
                                                Audit_Status ENUM('DONE','PUBLISH','DISABLE'),
                                                Audit_Action ENUM ('DO','PUBLISHED', 'SAVE','DISABLED','REJECT'),
                                                PRIMARY KEY(Id, Audit_Current, Audit_Version)) TYPE=INNODB;

CREATE TABLE Reportage_HIST (
                                                Id INT  AUTO_INCREMENT,
                                                Name VARCHAR(25) NOT NULL,
                                                Audit_Current ENUM('Y','N'),
                                                Audit_DateTime DATETIME NOT NULL,
                                                Audit_User VARCHAR(25) NOT NULL,
                                                Audit_Version INT  DEFAULT 1,
                                                Audit_Status ENUM('DONE','PUBLISH','DISABLE'),
                                                Audit_Action ENUM ('DO','PUBLISHED', 'SAVE','DISABLED','REJECT'),
                                                PRIMARY KEY(Id, Audit_Current, Audit_Version),
                                                INDEX rep_ind (Id, Audit_Current,Audit_Version),
                                                FOREIGN KEY (Id, Audit_Current, Audit_Version)
                                                        REFERENCES Reportage(Id, Audit_Current, Audit_Version)
                                                        ON UPDATE CASCADE ON DELETE SET NULL
                                               
                                                ) TYPE=INNODB;
cette partie n'est pas bonne.
                                                FOREIGN KEY (Id, Audit_Current, Audit_Version)
                                                        REFERENCES Reportage(Id, Audit_Current, Audit_Version)
                                                        ON UPDATE CASCADE ON DELETE SET NULL
cette partie "ON DELETE SET NULL" dit si tu effaces le tuple référencé par la clef primaire dans Reportage alors mets la valeur NULL dans la clef étrangere de Reportage_HIST.

Or ma clef étrangère n'a pas de valeur par défault à NULL (par définition des champs de ma table).... Il faudrait que je mette
Id INT AUTO INCREMENT DEFAULT NULL,
Audit_Current VARCAHR(1) DEFAULT NULL,
AUdit_Version INT DEFAULT NULL.

Il me semble que cela n'est tout bonnement pas possible!!!!

J'ai donc changé ma clef étrangère en mettant
...
Reportage_Id INT(11) DEFAULT NULL,
....
FOREIGN KEY (Reportage_Id)
REFERENCES Reportage(Id)
ON UPDATE CASCADE ON DELETE SET NULL

Ainsi, je peux créer des reportage via des inserts. (Je suis tout de même obligé de faire des insertions dans Reportage_HIST.)
Je peux également mettre à jour les reportages tjs via Insert+delete et non par update, (je sais que je m'embête, mais le but est d'avoir des tables auditables et que chaque version des reportages restent en base... et de cette manière, l'utilisateur peut faire des aller-retour au niveau des versions...

Voili, voilou, si je n'ai pas été super clair (il est tard) n'hésitez pas à me demander des précisions...