web-dev-qa-db-fra.com

Fonction déterministe pour obtenir la date d'aujourd'hui

J'essaie de créer une vue indexée à l'aide du code suivant (afin que je puisse le publier pour la répliquer comme une table):

CREATE VIEW lc.vw_dates
WITH SCHEMABINDING
AS

SELECT DATEADD(day, DATEDIFF(day, 0, GETDATE()), number) AS SettingDate
FROM lc.numbers
WHERE number<8

GO

CREATE UNIQUE CLUSTERED INDEX
idx_LCDates ON lc.vw_dates(SettingDate)

lC.Numbers est simplement une table avec 1 colonne (number) qui est incrémentée par la rangée 1-100.

Cependant, je continue à obtenir l'erreur:

La colonne 'réglage "dans la vue" lc.vw_dates "ne peut pas être utilisée dans un index ou des statistiques ou comme une clé de partition car elle n'est pas déterministe.

Je réalise que GETDATE() est non déterministe. Mais, existe-t-il un moyen de faire ce travail sans dessiner une table de calendrier?

4
bbailes

Vous ne pouvez pas utiliser la fonction GETDATE() comme base d'une vue persistante puisque la sortie de la fonction change le moment-deux-instance. Ce système SQL Server signifie dans l'erreur "car il n'est pas déterministe." Les résultats de la fonction doivent être prévisibles de manière prévisible chaque fois qu'ils sont appelés pour que SQL Server persiste les résultats.

Heureusement, il est facile de persister cette donnée une fois par jour à l'aide d'un emploi planifié. Peut-être utiliser SQL Server Agent ou Windows Job Scheduler, etc.

Ici, je crée la table des chiffres et la table pour contenir les 7 prochains jours:

CREATE TABLE dbo.Numbers
(
    Number INT NOT NULL
        CONSTRAINT PK_Numbers
        PRIMARY KEY CLUSTERED
);

;WITH cte AS
(
    SELECT TOP(100) Number = ROW_NUMBER() OVER (ORDER BY t1.num, t2.num)
    FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t1(num)
        , (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t2(num)
    ORDER BY t1.num * t2.num
)
INSERT INTO dbo.Numbers (Number)
SELECT cte.Number
FROM cte;

CREATE TABLE dbo.Next7Days
(
    SettingDate DATETIME NOT NULL
        CONSTRAINT PK_Next8Days
        PRIMARY KEY CLUSTERED
);

Planifiez cela pour arriver une fois par jour:

TRUNCATE TABLE dbo.Next7Days;

INSERT INTO dbo.Next7Days(SettingDate)
SELECT SettingDate = DATEADD(DAY, n.Number, DATEDIFF(DAY, 0, GETDATE()))
FROM dbo.Numbers n
WHERE n.Number < 8;

Étant donné que les dates des 7 prochains jours ne changent qu'une fois par jour, cette solution devrait bien fonctionner.

Le dbo.Next7Days La table contient les éléments suivants après avoir couru le code ci-dessus:

enter image description here

4
Max Vernon