2010-09-20 3 views
8

J'ai une procédure stockée T-SQL où je veux rechercher une valeur particulière et éventuellement limiter la recherche à des dates particulières si elles sont passées. Si les valeurs NULL sont passé pour l'une de ces dates, alors je veux les ignorer. La façon dont je pense à faire cela en définissant les dates d'entrée au minimum ou au maximum si elles sont nulles. Je préférerais ne pas coder les valeurs minimum et maximum. Donc, je me demande ce que l'équivalent SQL de la C# DateTime.MaxValue et DateTime.MinValue sont.Recherche SQL pour la date entre les valeurs ou Min/Max si NULL

Je pense à l'aide Coalesce comme si

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, <MinDateTime>) AND 
       Coalesce(@EndDate, <MaxDateTime>) 

Y at-il une fonction intégrée/constante/variable/ENUM je peux utiliser pour les variables <MinDateTime> et <MaxDateTime>?

Des suggestions?

Répondre

11

Il n'existe aucune fonctionnalité de ce type dans SQL Server. Vous pouvez facilement trouver le min and max dates autorisé dans BOL (1753-01-01 - 9999-12-31). Ou vous pouvez coder dur une autre date facilement (si vous travaillez vraiment avec des anniversaires, 1800-01-01 - 2100-12-31 suffirait probablement). Ou vous pouvez (si elle est la requête de plage que vous avez montré), avez COALESCE revenir à l'anniversaire lui-même:

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Birthday) AND 
       Coalesce(@EndDate, Birthday) 

Mais notez que ce ne sera pas nécessairement échelle bien pour très grandes tables.

Edité après accepter, pour répondre aux commentaires de OP

En général, pour SQL, si tu as besoin de données « de référence » souvent, vous ajoutez comme une table vous-même. (Google pour "table de calendrier" ou "table de nombre sql"). Donc, dans ce cas, si vous voulez, vous pouvez ajouter un « constantes » (ou peut-être la table « limites »):

create table Constants (
    Lock char(1) not null, 
    datetimeMin datetime not null, 
    datetimeMax datetime not null, 
    intMin int not null, 
    intMax int not null, 
    /* Other Min/Max columns, as required */ 
    constraint PK_Constants PRIMARY KEY (Lock), 
    constraint CK_Constants_Locked CHECK (Lock='X') 
) 
insert into Constants (Lock,datetimeMin,datetimeMax,intMin,intMax) 
select 'X','17530101','99991231',-2147483648,2147483647 

que vous pourriez alors faire référence dans les requêtes (soit par une sous-sélection, ou en croix de jonction à cette table). Par exemple.

SELECT EmployeeName 
FROM Employee, Constants 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Constants.datetimeMin) AND 
       Coalesce(@EndDate, Constants.datetimeMax) 

(la serrure, la clé primaire et contrainte de vérification, travailler ensemble pour faire en sorte que seule une seule ligne existera jamais dans ce tableau)

+0

Très intéressant. Je n'avais jamais vu le genre de motif Coalesce (@StartDate, Birthday) auparavant. Je pense que la création d'une variable appelée maxdate et mindate et la définition de ses valeurs aux dates codées en dur pourraient être beaucoup plus lisibles. Mais oui, l'info principale que je recherchais était l'absence des énumérations/constantes dans SQL – Chaitanya

+0

Re COALESCE tour - +1 à l'affirmation selon laquelle il ne s'agirait pas de grandes tables, SQL Server ne semble pas pouvoir utiliser index sur la colonne anniversaire. Le codage dur des dates min et max fonctionne bien avec l'index. –

3

Il n'y a pas de fonctions intégrées pour obtenir les valeurs de temps de date minimum ou maximum. Vous devez coder les valeurs ou récupérer les valeurs de la base de données.

Si les paramètres sont NULL, vous pouvez simplement sélectionner les dates min & max du tableau Employee.

IF (@StartDate IS Null) 
BEGIN 
SELECT @StartDate = MIN(Birthday) FROM Employee 
END 


IF (@EndDate IS Null) 
BEGIN 
SELECT @EndDate = MAX(Birthday) FROM Employee 
END 

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN @StartDate AND @EndDate 
+1

Je ne pense pas que ce soit ce que signifiait Chaitanya. –

+0

+1 Ce n'est peut-être pas exactement ce que Chaitanya demandait mais il répond assez bien aux exigences. Aucun codage en dur de datetime min et max nécessaire et même requête peut être utilisé pour les cas NULL ainsi – InSane

4

Pour SQL Server spécifiquement, selon BOL, les limites sont :

  • datetime: 01/01/1753 00:00:00 par 9999-12-31 23: 59: 59,997
  • smalldatetime: 1900-01-01 00:00:00 par 2079-06- 06 23: 59: 29.998
  • date: 0001-01-01 à 9999-12-31
  • datetime2: 0001-01-01 00:00:00 à 9999-12-31 23:59:59.9999999

Comme vous pouvez le voir, cela dépend de votre type de données exact.

Quant à la requête, je le ferais comme ceci:

SELECT EmployeeName 
FROM Employee 
WHERE EmployeeID = @EmployeeId 
AND (@StartDate IS NULL 
    OR Birthday >= @StartDate) 
AND (@EndDate IS NULL 
    OR Birthday <= @EndDate) 
+0

+1 pour les références. En ce qui concerne la requête - il doit être testé, 'BETWEEN ... COALESCE' pourrait être plus compréhensible pour le planificateur de requêtes. – Unreason

Questions connexes