2011-01-25 3 views
4

Nous développons actuellement une application dans laquelle plusieurs entités ont des heures d'ouverture associées. Les heures d'ouverture peuvent s'étendre sur plusieurs jours ou peuvent être contenues dans une seule journée.Heures d'ouverture Design de la base de données

Ex. Ouvre le lundi à 6h00 et ferme le vendredi à 18h00.

Ou

lundi à 06h00 ouvre et ferme lundi à 15h00.

En outre, une entité peut avoir plusieurs ensembles d'heures d'ouverture par jour. Jusqu'ici, le meilleur design que j'ai trouvé, est de définir une heure d'ouverture composée des éléments suivants:

StartDay, StartTime, EndDay et EndTime.

Cette conception permet toute la flexibilité nécessaire. Cependant, l'intégrité des données devient un problème. Je n'arrive pas à trouver une solution qui interdira les chevauchements (dans la base de données).

S'il vous plaît partagez votre opinion.

EDIT: La base de données est Microsoft SQL Server 2008 R2

+1

Quel système de base de données utilisez-vous? Cela nous aidera à définir ce que nous pouvons offrir en termes de solutions (via des contraintes, des déclencheurs, des champs calculés, etc.) –

Répondre

1

présumant un cadre de déclenchement robuste

sur insert/mise à jour vous vérifier si la nouvelle date de début ou fin tombe à l'intérieur d'une gamme existante. Si c'est le cas, vous annulez le changement.

CREATE TRIGGER [dbo].[mytable_iutrig] on [mytable] FOR INSERT, UPDATE AS 

IF (SELECT COUNT(*) 
FROM inserted, mytable 
WHERE (inserted.startdate < mytable.enddate 
      AND inserted.startdate > mytable.startdate) 
     OR (inserted.enddate < mytable.enddate 
      AND inserted.enddate > mytable.startdate)) > 0 
BEGIN 
    RAISERROR --error number 
    ROLLBACK TRANSACTION 
END 
+1

Étant donné que le déclencheur est déclenché après que l'insertion ou la mise à jour a été exécutée, je vais devoir annuler les modifications. Juste comme tu décris. Il semble que je ne peux pas être sûr de supprimer la bonne ligne insérée, aussi je ne vois pas un moyen de revenir en arrière une mise à jour? – DEHAAS

+0

Ajout de l'instruction de restauration –

+0

Cela semble être une solution plutôt géniale. Puis-je m'assurer que les problèmes de simultanéité n'auront pas le déclencheur être exécuté au mauvais moment? – DEHAAS

2

Pensez à stocker votre StartDay et StartTime, mais ont une valeur pour le nombre d'heures qu'il est ouvert. Cela garantira que votre date-heure de fermeture est après l'ouverture.

OpenDate -- day of week? e.g. 1 for Monday 
OpenTime -- time of day. e.g. 08:00 
DurationInHours -- in hours or mins. e.g. 15.5 
+0

J'ai également pensé à cette solution. Cependant, bien qu'il résout le problème de chevauchement des périodes pour une seule définition d'heure d'ouverture, le problème persiste lorsqu'une entité a plusieurs définitions d'heures d'ouverture. – DEHAAS

0

Une table avec une seule colonne TimeOfChangeBetweenOpeningAndClosing? Plus sérieusement, je ne m'inquiéterais probablement pas trop de créer une structure de base de données unique pour représenter tout, éventuellement vous voudrez probablement un système impliquant des récurrences, des fermetures planifiées, etc Persist objets représentant ceux-ci, puis évaluez-les pour connaître les heures de fermeture/d'ouverture.

+0

Comment ne stocker que la valeur delta empêcher le chevauchement? –

+0

Vous devez avoir un jour de référence comme point de départ, mais ce n'est peut-être pas une mauvaise solution. Le plus gros problème que je vois ici est que pour ajuster une période de temps, vous devez également ajuster les deux de chaque côté pour compenser. – Kendrick

+0

+1 pour avoir réfléchi en dehors de la boîte et pour avoir dirigé la question vers la grande image. –

0

La détection et la prévention des périodes de chevauchement devront être effectuées au niveau de l'application. Bien sûr, vous pouvez essayer d'utiliser un déclencheur dans la base de données, mais à mon avis ce n'est pas un problème de base de données. La structure que vous avez trouvée est bonne, mais votre logique d'application devra prendre soin du chevauchement.

+0

Naturellement, ce serait une solution possible. Cependant, je préférerais être assuré que des données incohérentes sont impossibles, si une telle solution est possible. – DEHAAS

0

Cela ressemble à une bonne solution, mais vous devrez écrire une fonction de validation personnalisée. La validation de base de données intégrée (c'est-à-dire unique, inférieur à x, etc.) ne va pas le couper ici. Pour éviter les chevauchements, chaque fois que vous insérez un enregistrement dans la base de données, vous devez sélectionner les enregistrements existants et les comparer ...

+0

Est-il possible d'écrire ce type de validation dans la base de données, ou dois-je le mettre dans ma logique métier au niveau de l'application? – DEHAAS

+0

Vous pouvez l'écrire au niveau de la base de données, tel que suggéré par @Russell Steen. – Kendrick

0

D'abord la logique, deux intervalles se chevaucheront si le début La valeur de l'un tombe entre le début et la fin de l'autre. C'est beaucoup plus facile si nous avons des datetimes combinées, au lieu de date1, time1 et date2, time2. Donc, une requête pour trouver un chevauchement ressemble à ceci.

select openingId 
    from opening o1 
    join opening o2 on o1.startDateTime 
      between o2.startDateTime 
       AND o2.endDateTime 

Vous pouvez mettre ceci dans un déclencheur et lancer une erreur si une correspondance est trouvée.

1

Il y a un article de Joe Celko sur le site SimpleTalk, sur here, qui traite un problème similaire, et présente suis élégante si la solution complexe. Ceci est probablement applicable à votre situation.

Questions connexes