Je développe en utilisant symfony 1.4 (et Doctrine) et ai une table de base de données MySQL avec un index unique sur plusieurs colonnes. Tout d'abord, la définition YAML de la table jusqu'à présent:unique par plusieurs colonnes et valeurs NULL
Campaign:
actAs:
Sluggable:
fields: [name]
canUpdate: true
uniqueBy: [merchant_id, deleted_at]
Timestampable: ~
SoftDelete: ~
columns:
merchant_id: { type: integer, notnull: true }
name: { type: string(255), notnull: true, notblank: true }
start_date: { type: date, notnull: true, notblank: true }
end_date: { type: date, notnull: true, notblank: true }
indexes:
unique_name: { fields: [name, merchant_id, deleted_at], type: unique }
relations:
Merchant: { local: merchant_id, foreign: id }
Comme vous pouvez le voir, je dois traiter avec des campagnes appartenant à des marchands. Une campagne connaît son marchand et a un nom (ainsi qu'une date de début et une date de fin). Le nom d'une campagne doit être unique - pas globalement mais pour ce marchand spécifique. Jusqu'à ici, j'aurais besoin d'un index unique sur le nom de la campagne et le marchand respectif. Mais comme la table "agit comme SoftDelete" et que l'utilisateur devrait être capable de créer une nouvelle campagne avec un nom qui existe déjà pour une campagne "soft-deleted", la colonne deleted_at
doit également faire partie de l'index unique. Vous voyez, l'unicité du nom d'une campagne ne concerne que les campagnes non supprimées du marchand respectif.
Venons-en maintenant au problème réel : Comme colonne deleted_at
est NULL pour toutes les campagnes non supprimées et les valeurs NULL dans un index unique sont toujours traités comme étant unique, toutes les campagnes sont autorisés à avoir des noms non-uniques - en le vrai sens. Je sais, cela s'applique aux tables MyISAM et InnoDB mais pas aux tables BDB. Cependant, passer à BDB n'est pas mon option préférée, si vous voyez ce que je veux dire.
Maintenant à venir à la question réelle: Quelles sont les autres options possibles en plus de changer le moteur MySQL à BDB? Une solution de contournement pourrait être de renommer une campagne qui est supprimée, par ex. name = 'DELETED AT ' + deleted_at + ': ' + name
. Ceci, d'une part, aurait l'avantage que toutes les campagnes à suppression de contenu auraient des noms uniques même dans le cas où elles sont restaurées (réinitialisation deleted_at
à NULL). La colonne deleted_at
ne devrait plus faire partie de l'index unique et, par conséquent, toutes les campagnes (non supprimées, effacées et restaurées une seule fois) auraient un nom unique - concernant le marchand respectif. Mais, d'un autre côté, je ne pense pas que ce soit la solution la plus élégante. Quelles sont vos opinions et votre expertise à ce sujet?
Je vous remercie beaucoup et je suis heureux de vos contributions.
Flinsch.
Ike, merci pour votre réponse. J'ai eu une idée très similaire aussi. Et je pense que l'indicateur supplémentaire 'is_deleted' n'est pas vraiment nécessaire car je peux vérifier que' deleted_at' est 0 ou pas. Cependant, je l'ai déjà ignoré, parce que je ne sais pas exactement si définir manuellement 'deleted_at' à une valeur NOT NULL aurait des conséquences imprévues sur la génération de listes d'objets, etc. - comme' deleted_at' est quelque chose comme une «colonne magique "de symfony/Doctrine. Mais je pense que je vais essayer ... :) – Flinsch
MySQL 5.7 peut vous aider avec des colonnes virtuelles !: http://stackoverflow.com/questions/42064759/how-to-do-unique-constraint-works- avec-null-valeur-dans-mysql/42291845 # 42291845 – Nothus