2017-10-20 8 views
0

Je travaille sur un projet personnel et pour la première fois de ma vie j'essaie de faire une base de données qui est normalisée (au moins jusqu'au premier niveau de normalisation). Voici la table impliquée dans mon problème:Quel est le problème avec mes contraintes de clé étrangère mysql?

CREATE TABLE `reoccurrences` (
    `name` varchar(15) NOT NULL DEFAULT '', 
    `username` varchar(31) NOT NULL DEFAULT '', 
    `amount` float(7,2) NOT NULL DEFAULT '0.00', 
    `action` varchar(15) NOT NULL DEFAULT '', 
    `frequency` varchar(15) NOT NULL DEFAULT '', 
    PRIMARY KEY (`name`,`username`), 
    KEY `fk_reoccurrences_user` (`username`), 
    KEY `fk_reoccurrences_action` (`action`), 
    KEY `fk_reoccurrences_frequency` (`frequency`), 
    CONSTRAINT `fk_reoccurrences_action` FOREIGN KEY (`action`) REFERENCES `actions` (`name`), 
    CONSTRAINT `fk_reoccurrences_frequency` FOREIGN KEY (`frequency`) REFERENCES `frequencies` (`name`), 
    CONSTRAINT `fk_reoccurrences_user` FOREIGN KEY (`username`) REFERENCES `users` (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `days` (
    `reoccurrence` varchar(15) NOT NULL, 
    `username` varchar(31) NOT NULL DEFAULT '', 
    `day` tinyint(2) NOT NULL, 
    PRIMARY KEY (`reoccurrence`,`username`,`day`), 
    KEY `fk_days_reoccurrence2` (`username`), 
    CONSTRAINT `fk_days_reoccurrence` FOREIGN KEY (`reoccurrence`) REFERENCES `reoccurrences` (`name`), 
    CONSTRAINT `fk_days_reoccurrence2` FOREIGN KEY (`username`) REFERENCES `reoccurrences` (`username`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Notez, le problème principal (je crois) est entre ces deux tables. Il y a plusieurs autres tables connexes mais si je commence à les lister, ce post serait très long. Si vous voulez voir la structure de données complète, vous pouvez voir mon projet sur github ici: https://github.com/dallascaley/finance (et je m'excuse pour le blasphème/le manque de bon sens dans mon readme github, il n'était pas destiné au public)

problème arrive quand je commence à ajouter des données à ces tables. Voici les données que j'ai:

reoccurrences: 

name, username, amount, action, frequency 
Pay , dallas , 2500 , credit, bi-weekly 
Rent, dallas , 1400 , debit , monthly 

days: 

reoccurrence, username, day 
Rent  , dallas , 1 

ignorer le fait que je n'ai pas un jour ou plusieurs jours pour la liste de paiement. Pour une raison quelconque, lorsque la table est dans cet état, je ne peux pas supprimer l'enregistrement Pay de la table de récurrence. Quand je lance ceci:

DELETE FROM reoccurrences WHERE `name` = 'Pay' AND `username` = 'dallas'; 

Je reçois l'erreur suivante:

Cannot delete or update a parent row: a foreign key constraint fails (`test`.`days`, CONSTRAINT `fk_days_reoccurrence2` FOREIGN KEY (`username`) REFERENCES `reoccurrences` (`username`)) 

Comment pourrais-je changer ma structure de table pour résoudre ce problème?

Répondre

2

Vous avez probablement juste besoin de fixer vos contraintes dans le tableau days pour utiliser la clé composite à partir reoccurrences:

CREATE TABLE `days` (
    `reoccurrence` varchar(15) NOT NULL, 
    `username` varchar(31) NOT NULL DEFAULT '', 
    `day` tinyint(2) NOT NULL, 
    PRIMARY KEY (`reoccurrence`,`username`,`day`), 
    CONSTRAINT `fk_days_reoccurrence` FOREIGN KEY (`reoccurrence`,`username`) REFERENCES `reoccurrences` (`name`,`username`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Comme vous pouvez le voir, je changé fk_days_reoccurrence à une touche de composition et complètement abandonné fk_days_reoccurrence2, la clé et références de clés étrangères.

+0

Merci, vous avez eu raison. Je ne peux pas croire à ma décennie de développement de logiciels que je n'ai jamais travaillé dans une entreprise qui imposait une bonne structure de données (en plus de HauteLook, mais ils ne me laissaient pas près de la base de données) –

+0

les contraintes de la clé étrangère originale de votre table 'days' à votre' reoccurrence' n'étaient pas bonnes. Ils ont chacun indiqué une relation de 1 à plusieurs entre 'reoccurrence' et' days' sur leurs colonnes respectives 'name (1) -> reoccurrence (n)' et 'username (1) -> nom d'utilisateur (n)', mais la table 'reoccurrence' n'a pas appliqué l'instance de' name' ou 'username'. Ainsi, lorsque vous avez essayé de supprimer 'reoccurrence', la contrainte référentielle sur' nom d'utilisateur 'a empêché la suppression puisque 'jours' référencé' username' 'dallas', même s'il y avait 2 instances de' dallas'. – Sentinel