La colonne calculée ne peut pas être conservée car la colonne n'est pas déterministe

9

Je sais que ce n'est pas la première fois que ce type de question est posée.

Mais pourquoi dans le scénario suivant la colonne calculée persistante est-elle créée "non déterministe". La réponse devrait toujours être la même, non?

CREATE TABLE dbo.test (Id INT, EventTime DATETIME NULL, PosixTime INT NOT NULL)
GO

DECLARE @EventTime DATETIME =  '20181001 12:00:00'
DECLARE @GPSTime INT = DATEDIFF(SECOND, '19700101', @EventTime)
INSERT INTO dbo.Test(Id, EventTime, PosixTime) 
VALUES (1, @EventTime, @GPSTime)
    , (2, NULL, @GPSTime)
GO

SELECT * FROM dbo.test
GO

ALTER TABLE dbo.test ADD UTCTime AS CONVERT(DATETIME2,ISNULL(EventTime, DATEADD(SECOND, PosixTime, CONVERT(DATE,'19700101'))),112) PERSISTED
GO

Msg 4936, niveau 16, état 1, ligne 42 La colonne calculée «UTCTime» dans la table «test» ne peut pas être conservée car la colonne n'est pas déterministe.

Je pense que je suis ici les règles déterministes .

Est-il possible de créer une colonne calculée persistante ici?

Mazhar
la source

Réponses:

8

La conversion d'une chaîne en une date sans numéro de style n'est pas déterministe, il n'y a également aucune raison d'utiliser un numéro de style lors de la conversion d'une date ou d'un datetime en datetime2. Essayer:

ALTER TABLE dbo.test 
    ADD UTCTime AS CONVERT(datetime2,ISNULL(EventTime, 
    DATEADD(SECOND, PosixTime, CONVERT(datetime,'1970-01-01',120)))) 
    PERSISTED;

Bien que je sois curieux de savoir pourquoi vous devez conserver cette colonne. Si c'est le cas, vous pouvez l'indexer, vous n'avez pas besoin de conserver une colonne pour l'indexer ...

Aaron Bertrand
la source
11

Vous devez utiliser un style déterministe lors de la conversion à partir d'une représentation sous forme de chaîne .

Vous n'utilisiez pas un style déterministe avec la conversion de chaîne en date.

Vous spécifiiez inutilement un style lors de la conversion de date en datetime2.

Il y a un mélange confus de types de données date / heure dans la question.

Cela fonctionne (produire une datetimecolonne):

ALTER TABLE dbo.test 
ADD UTCTime AS 
    ISNULL
    (
        EventTime,
        DATEADD
        (
            SECOND, 
            PosixTime, 
            CONVERT(datetime, '19700101', 112)
        )
    )
    PERSISTED;

Comme Aaron l'a mentionné (nous répondions simultanément), vous n'avez pas besoin de conserver une colonne déterministe pour l'indexer.

Paul White 9
la source