Kolom yang dikomputasi tidak dapat dipertahankan karena kolom tersebut tidak deterministik

9

Saya tahu ini bukan kali pertama jenis pertanyaan ini ditanyakan.

Tetapi mengapa dalam skenario berikut adalah kolom yang dihitung tetap dibuat "non-deterministik". Jawabannya harus selalu sama, bukan?

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, Level 16, Negara 1, Baris 42 Kolom terkomputasi 'UTCTime' dalam tabel 'test' tidak dapat dipertahankan karena kolom tersebut tidak deterministik.

Saya pikir saya mengikuti aturan deterministc di sini .

Apakah mungkin untuk membuat kolom yang dihitung tetap di sini?

Mazhar
sumber

Jawaban:

8

Mengonversi string ke tanggal tanpa nomor gaya tidak bersifat deterministik, juga tidak ada alasan untuk menggunakan nomor gaya saat mengubah tanggal atau waktu ke datetime2. Mencoba:

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

Meskipun saya ingin tahu mengapa Anda perlu bertahan di kolom ini. Jika demikian, Anda dapat mengindeksnya, Anda tidak perlu melanjutkan kolom untuk mengindeksnya ...

Aaron Bertrand
sumber
11

Anda perlu menggunakan gaya deterministik saat mengkonversi dari representasi string .

Anda tidak menggunakan gaya deterministik dengan konversi dari string ke date.

Anda tidak perlu menentukan gaya saat mengkonversi dari tanggal ke datetime2.

Ada campuran membingungkan tipe data tanggal / waktu dalam pertanyaan.

Ini berfungsi (menghasilkan datetimekolom):

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

Seperti yang Aaron sebutkan (kami menjawab secara bersamaan), Anda tidak perlu mempertahankan kolom deterministik untuk mengindeksnya.

Paul White 9
sumber