2016-06-01 1 views
2

Dites qu'il existe une table appointment_booking pour une liste de gestionnaires (ou HR) avec startDatetime et endDatetime, puis comment concevoir la table avec soin de sorte qu'elle n'accepte pas l'entrée suivante qui chevauche pour même gestionnaire s'il/elle a rendez-vous avec une autre personne.SQL Interview: Empêcher la plage de dates chevauchantes

Si Gestionnaire: Un a un rendez-vous de 2016-01-01 11:00 to 2016-01-01 14:00 avec Employee-1 alors si Employee-2 (ou someother employé) tente de réserver un rendez-vous de 20-16-01-01 13:00 to 16:00 alors il ne devrait pas permettre.

Remarque: Il s'agit de concevoir la table, donc les déclencheurs/procédures ne sont pas encouragés.

+6

Pour appliquer cette contrainte, il faut un déclencheur ou une fonction définie par l'utilisateur (au moins dans la plupart des bases de données). –

+0

Si c'est vraiment une question SQL Interview, vous pouvez répondre simplement que, au moment de la conception, ce n'est pas possible. –

+0

Vous pouvez le faire dans SQL Server si vous modélisez également les périodes de temps libre, avez des références croisées qui relient chaque période de temps à son prédécesseur et successeur, et écrivez des instructions MERGE vraiment horribles pour gérer l'insertion/suppression (où, le plus souvent, vous devez fractionner une période libre en en mettant une à jour, en insérant une nouvelle ligne et en insérant le nouveau rendez-vous, le tout dans une seule instruction afin que les clés étrangères restent satisfaites). C'est faisable mais souvent les coûts sont plus élevés que la valeur. –

Répondre

1

Au lieu d'insérer des plages, vous pouvez insérer des tranches de temps. Vous pouvez faire les tranches aussi large que vous voulez, mais prétendez que vous pouvez réserver un gestionnaire pour 30 minutes à la fois. Pour réserver de 11h30 à 12h00, vous devez insérer une ligne avec la valeur de l'heure à 11h30. Pour réserver de 11h30 à 12h30, vous insérez deux rangées, l'une à 11h30, l'autre à 12h00. Ensuite, vous pouvez simplement utiliser une contrainte de clé primaire ou une contrainte unique pour éviter la sur réservation.

create table appointment_booking (
    manager char not null, 
    startSlice DateTime, 
    visiting_employee varchar2(255), 
    primary key (manager, startSlice) 
) 

Je sais que cela ne correspond pas exactement à votre prémisse de la table avec un début et de fin, mais si vous avez le contrôle sur la structure de la table, cela fonctionnerait.

0

CONTRÔLE CONTRAINTE + FONCTION (ce qui est aussi proche que je peux obtenir une réponse DDL)

Vous pouvez créer une fonction scalaire - « SCHEDULE_OPENING_EXISTS() » qui prend début, fin, EMPLOYEEID comme entrées et renvoie des résultats vrais ou faux.

Ensuite, vous pouvez créer une contrainte de vérification sur la table

CREATE TABLE... 
    WITH CHECK ADD CONSTRAINT OPENING_EXISTS 
    CHECK (SCHEDULE_OPENING_EXISTS(begin, end, employeeID)) = 'True') 

Triggers:

J'essaie d'éviter les déclencheurs où je peux. Ils ne sont pas mauvais en soi - mais ils ajoutent une nouvelle couche de complexité à votre application. Si vous ne pouvez pas l'éviter, vous aurez besoin d'un INSERT INSTEAD, et aussi d'un INSTEAD OF UPDATE (vraisemblablement). Référence Technet ici: https://technet.microsoft.com/en-us/library/ms179288%28v=sql.105%29.aspx

Gardez à l'esprit, si vous rejetez une tentative d'insertion/mise à jour, si vous avez besoin de la communiquer à l'utilisateur.

INTERFACE PROCÉDURES/UTILISATEUR STORED:

Est-ce qu'un travail de procédure stockée pour votre situation? Scénario type:

  1. Interface utilisateur: l'utilisateur doit consulter l'horaire de la ou des personnes avec lesquelles il planifie un rendez-vous.

  2. Depuis l'interface utilisateur - essayez une insertion/mise à jour en utilisant un proc stocké. Avoir re-vérifier (ouverture de dernière minute) l'ouverture (retourner un échec si l'ouverture n'existe plus), puis insérer/mettre à jour conditionnellement si une ouverture existe toujours (retourner un message de réussite).

Si le proc retourne un échec à l'interface utilisateur, poignée dans l'interface utilisateur en ré-interroger le calendrier visible de toutes les parties, accompagné d'un message d'erreur.

+0

note: la question concerne les contraintes (vérification), la modélisation des données et le DDL en SQL. L'application ou l'interface utilisateur ne sont pas pertinentes ici, tout comme les procédures stockées. – wildplasser

+0

@wildplasser - Ajout d'une option CHECK CONSTRAINT à la réponse ... pas entièrement DDL, mais ... plus proche. – Chains

0

Je pense que ces types de questions sont intéressants parce que chaque fois que vous concevez une base de données, il est important de connaître les exigences de l'application qui interagira avec votre base de données.

Cela dit, tant que l'application peut faire référence à plusieurs tables, je pense que la réponse de Chris Steele est un bon début que je vais construire sur ...

Je veux 2 tables. Le premier tableau divise un jour en parties (tranches), en fonction des besoins de l'entreprise. Chaque tranche serait la clé primaire de cette table. Personnellement, je choisirais des tranches de 15 minutes qui équivaut à 96 parties de jour. Chaque partie journalière de cette table aurait un "début de bloc" et un temps de "fin de bloc" qui seraient référencés par l'application de planification lorsqu'un utilisateur a sélectionné une heure de début réelle et une heure de fin réelle pour la réunion. L'application aurait besoin d'appliquer une logique telle que deux « OU » entre 3 « et » déclarations afin de voir si un particulier BlockID sera inséré dans votre table de rendez-vous:

  • début réel> = démarrage du bloc et réelle début < bloc fin
  • fin réelle> début du bloc et la fin réelle < fin du bloc
  • début réel < début du bloc et la fin réelle> fin du bloc

Cela varie légèrement de la réponse de Chris Steele dans e il utilise deux tables. Les horodatages réels peuvent toujours être insérés dans votre table d'applications, mais la logique ne leur est appliquée que lors de la comparaison avec la table TimeBlocks. Dans ma table de rendez-vous, je préfère les dates de rupture dans différentes parties pour une analyse multi-plateforme (notre organisation utilise SGBDR multiples ainsi que SAS pour l'analyse):

CREATE TABLE TimeBlocks (
      blockID Number(X) NOT NULL, 
      blockStart DateTime NOT NULL, 
      blockEnd DateTime NOT NULL, 
    primary key (blockID) 
); 


CREATE TABLE Appointments (
      mgrID INT NOT NULL, 
      yr INT NOT NULL, 
      mnth INT NOT NULL, 
      day INT NOT NULL, 
      blockID INT NOT NULL, 
      ApptStart DateTime NOT NULL, 
      ApptEnd DateTime NOT NULL 
      empID INT NOT NULL, 
    primary key (mgrID, yr, mnth, day, blockID), 
    CONSTRAINT timecheck 
      check (ApptStart < ApptEnd) 
);