2008-11-21 38 views
6

(Điều này có liên quan đến Floor a date in SQL server.)Máy chủ SQL: Tầng một ngày trong máy chủ SQL, nhưng vẫn xác định

Biểu thức xác định có tồn tại trên sàn DATETIME không? Khi tôi sử dụng điều này như một công thức cột tính:

DATEADD(dd, DATEDIFF(dd, 0, [datetime_column]), 0) 

tôi nhận được một lỗi khi tôi đặt một chỉ mục trên cột rằng:

Không thể tạo index vì cột then chốt 'EFFECTIVEDATE' là phi xác định hoặc không chính xác.

Nhưng cả DATEDIFF và DATEADD đều là hàm xác định theo định nghĩa. Đâu là bắt? Có thể không?

Trả lời

3

Tôi đoán rằng đây là lỗi của một số loại. Trong SQL 2005, tôi đã có thể tạo ra một khung nhìn được lập chỉ mục mà không có vấn đề gì (mã dưới đây). Khi tôi đã cố gắng chạy nó trên SQL 2000 mặc dù tôi đã nhận được lỗi tương tự như bạn đang nhận được.

Sau đây có vẻ như hoạt động trên SQL 2000, nhưng tôi nhận được cảnh báo rằng chỉ mục sẽ bị bỏ qua VÀ bạn sẽ phải chuyển đổi mỗi lần bạn chọn từ chế độ xem.

CONVERT(CHAR(8), datetime_column, 112) 

trình trong SQL 2005:

CREATE TABLE dbo.Test_Determinism (
    datetime_column DATETIME NOT NULL DEFAULT GETDATE()) 
GO 

CREATE VIEW dbo.Test_Determinism_View 
WITH SCHEMABINDING 
AS 
    SELECT 
     DATEADD(dd, DATEDIFF(dd, 0, [datetime_column]), 0) AS EffectiveDate 
    FROM 
     dbo.Test_Determinism 
GO 

CREATE UNIQUE CLUSTERED INDEX IDX_Test_Determinism_View ON dbo.Test_Determinism_View (EffectiveDate) 
GO 
2

Cột [datetime_column] của bạn có giá trị mặc định được đặt thành "getDate()" ??

Nếu vậy, kể từ getdate() chức năng là không xác định, điều này sẽ gây ra lỗi này ...

Cho dù một hàm người dùng định nghĩa là xác định hoặc không xác định phụ thuộc vào cách các chức năng được mã hóa. Các hàm do người dùng xác định là xác định nếu:

  1. Hàm này được ràng buộc lược đồ.
  2. Tất cả các chức năng được xây dựng hoặc do người dùng xác định được gọi bởi hàm do người dùng định nghĩa là xác định.
  3. Phần thân của hàm tham chiếu không có đối tượng cơ sở dữ liệu nào nằm ngoài phạm vi của hàm. Ví dụ: hàm xác định không thể các bảng tham chiếu khác ngoài bảng các biến cục bộ với hàm .
  4. Chức năng không gọi bất kỳ thủ tục được lưu trữ mở rộng nào .

Các hàm do người dùng xác định không đáp ứng các tiêu chí này được đánh dấu là không xác định. Các chức năng không xác định được xây dựng trong không được phép trong phần thân của các hàm do người dùng định nghĩa.

+0

Có. Nhưng lỗi từ đâu đến? – Tomalak

+0

getDate là không xác định Tôi tin rằng đó sẽ là lý do – kristof

+0

Vâng đó là lý do tại sao! –

1

Hãy thử điều này:

CAST(FLOOR(CAST([datetime_column] as FLOAT)) AS DateTime) 

Nó nên đi nhanh hơn nhiều so với tùy chọn CONVERT.

+0

CAST không xác định giá trị datetime. – Tomalak

+0

Chết tiệt, đó là những gì tôi đã thử. – StingyJack

0

Nhìn vào that question asked and answered by Cade Roux. Có lẽ giải pháp sẽ được tạo một hàm sử dụng VỚI SCHEMABINDING và sau đó sử dụng nó trong cột tính

EDIT

Tôi hiểu rằng bạn Mục đích là để có thể có một chỉ mục trên cột đó.

Nếu không thể thực hiện với cột được tính thì có lẽ tùy chọn duy nhất là tạo cột thông thường và sửa đổi dữ liệu trong cột đó mỗi lần bạn cập nhật dữ liệu dựa trên đó.(Nói trong trigger)

+0

Tôi đã thử điều đó, cảm ơn mẹo. Nhưng than ôi, cùng một lỗi. – Tomalak

+0

Bạn có tìm được giải pháp không? – kristof

0

tôi muốn đề nghị những phần nào đơn giản hơn:

cast(cast([datetime_column] as int) as datetime) 

nhưng tôi nghi ngờ bạn sẽ chạy vào cùng một vấn đề.

Bây giờ nếu sự cố đang được truyền trở lại ngày giờ, bạn có thể muốn xem xét chỉ sử dụng cast([datetime_column] as int) làm trường riêng biệt, chỉ dành cho chỉ mục.

+0

Vấn đề cũng là với việc đúc * từ * datetime (hoặc chuyển đổi() ing, cho vấn đề đó). – Tomalak

1

Dưới đây là câu trả lời hết sức để trả lời câu hỏi ban đầu:

Hãy thử điều này:

/* create a deterministic schema bound function */ 
CREATE FUNCTION FloorDate(@dt datetime) 
RETURNS datetime 
WITH SCHEMABINDING 
AS 
BEGIN 
    RETURN CONVERT(datetime, FLOOR(CONVERT(float, @dt))) 
END 
GO 

Để kiểm tra, hãy thử những điều sau đây. Xin lưu ý việc sử dụng các "cứ khăng khăng" cho cột tính toán và sử dụng các [dbo.] Khi đề cập đến chức năng

/*create a test table */ 
CREATE TABLE [dbo].[TableTestFloorDate](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [TestDate] [datetime] NOT NULL, 
    [TestFloorDate] AS ([dbo].[FloorDate]([TestDate])) PERSISTED, 
CONSTRAINT [PK_TableTestFloorDate] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
) 

Bây giờ bạn có thể thêm một chỉ mục trên cột tính (nhưng xem Gotcha sau)

CREATE INDEX IX_TestFloorDate ON [dbo].[TableTestFloorDate](TestFloorDate) 

Chèn một số dữ liệu ngẫu nhiên nhiều lần như bạn muốn nhưng nhiều hơn (1000) là tốt hơn nếu bạn muốn kiểm tra việc sử dụng chỉ số/thực hiện kế hoạch

INSERT INTO TableTestFloorDate (TestDate) VALUES(convert(datetime, RAND()*50000)) 

Lấy kết quả

SELECT * FROM TableTestFloorDate WHERE TestFloorDate='2013-2-2' 

Bây giờ đây là GOTCHA ... Chỉ mục đã được tạo trên cột được tính không được sử dụng! Thay vào đó, ngay cả khi chọn dữ liệu trên trường tồn tại TestFloorDate, SQLServer (hoặc ít nhất là phiên bản của tôi) thích một chỉ mục trên TestDate.

CREATE INDEX IX_TestFloorDate ON [dbo].[TableTestFloorDate](TestDate) 

Tôi khá chắc chắn (từ bộ nhớ) mà chỉ số về tính toán, vẫn kiên trì cột là lợi ích từ góc độ hiệu suất - Tôi đoán bạn sẽ chỉ phải thử/kiểm tra cho tập quán cụ thể của riêng bạn

(Hy vọng tôi đã giúp!)

+0

Tôi không có cách nào để kiểm tra nó ngay bây giờ. Đây có phải là SQL Server 2000 tương thích (tôi biết nó là cổ xưa, nhưng các thẻ trong câu hỏi chỉ ra phiên bản này)? – Tomalak

+0

Ở trên đã được thử nghiệm trong Sql2012 nhưng từ bộ nhớ tôi không thấy lý do tại sao nó sẽ không hoạt động trên Sql2k theo cách chính xác mô tả ở trên – dunxz