2011-08-11 34 views
5

Tôi đang sửa đổi truy vấn hiện tại cho khách hàng và tôi gặp phải sự cố hơi khó hiểu.Chuyển đổi ngày giờ SQL không thay đổi khi không có chuyển đổi nào nên được thực hiện

Ứng dụng khách của chúng tôi sử dụng SQL Server 2008 R2 và cơ sở dữ liệu được đề cập cung cấp cho người dùng khả năng chỉ định trường tùy chỉnh cho một trong các bảng của nó bằng cách sử dụng cấu trúc EAV. Tất cả các giá trị được lưu trữ trong cấu trúc này là varchar(255) và một số trường được dự định lưu trữ ngày. Truy vấn được đề cập đang được sửa đổi để sử dụng hai trường này và so sánh chúng (một là bắt đầu, trường còn lại là kết thúc) so với ngày hiện tại để xác định hàng nào là "hiện tại".

Vấn đề tôi gặp phải là một phần của truy vấn thực hiện CONVERT(DateTime, eav.Value) để chuyển varchar thành DateTime. Quá trình chuyển đổi bản thân tất cả succedd và tôi có thể bao gồm các giá trị như một phần của mệnh đề SELECT, nhưng một phần của câu hỏi được đưa ra cho tôi một lỗi chuyển đổi:

Conversion failed when converting date and/or time from character string. 

Kicker thực là thế này: nếu tôi xác định cơ sở cho điều này truy vấn (nhận danh sách các thực thể có hai giá trị trường tùy chỉnh được làm phẳng thành một hàng) làm chế độ xem và chọn chế độ xem và lọc chế độ xem theo số getdate(), sau đó nó hoạt động chính xác nhưng không thành công nếu tôi thêm tham gia vào một giây bảng sử dụng một trong các trường (không phải ngày) từ chế độ xem. Tôi nhận ra rằng điều này có thể hơi khó để theo dõi, vì vậy tôi có thể đăng một truy vấn ví dụ nếu muốn, nhưng câu hỏi này đã nhận được một chút dài.

Tôi đã thử tạo lại cấu trúc cơ bản trong cơ sở dữ liệu khác và bao gồm dữ liệu mẫu, nhưng cơ sở dữ liệu mới hoạt động như mong đợi, vì vậy tôi bị mất ở đây.

EDIT Trong trường hợp đó là hữu ích, đây là báo cáo kết quả cho quan điểm:

create view Festival as 
select 
    e.EntityId as FestivalId, 
    e.LookupAs as FestivalName, 
    convert(Date, nvs.Value) as ActivityStart, 
    convert(Date, nve.Value) as ActivityEnd 

from tblEntity e 

left join CustomControl ccs on ccs.ShortName = 'Activity Start Date' 
left join CustomControl cce on cce.ShortName = 'Activity End Date' 
left join tblEntityNameValue nvs on nvs.CustomControlId = ccs.IdCustomControl and nvs.EntityId = e.EntityId 
left join tblEntityNameValue nve on nve.CustomControlId = cce.IdCustomControl and nve.EntityId = e.EntityId 

where e.EntityType = 'Festival' 

Truy vấn thất bại là thế này:

select * 

from Festival f 

join FestivalAttendeeAll fa on fa.FestivalId = f.FestivalId 

where getdate() between f.ActivityStart and f.ActivityEnd 

Tuy nhiên, công trình này:

select * 

from Festival f 

where getdate() between f.ActivityStart and f.ActivityEnd 

(EntityId/FestivalId ar e int columns)

+0

có thể là do ngôn ngữ, và Hoa Kỳ so với các ngày được định dạng không phải của Hoa Kỳ ... Kiểm tra cài đặt ngôn ngữ ... Bạn có thể đăng dữ liệu ví dụ thể hiện hành vi không? –

+0

Có thể bắt đầu với truy vấn đầu tiên không thành công và đăng nó. – Paparazzi

+0

@Mitch: Đó sẽ là suy nghĩ đầu tiên của tôi nếu tôi trả lời là tốt, nhưng đây là tất cả các ngày ở Hoa Kỳ, được định dạng theo định dạng 'Jan 1 2011 12:00 AM' hoặc '1/1/2011 12:00 AM '. Phần khó hiểu là lỗi có vẻ gắn liền với một cái gì đó (bởi logic của tôi, mà rõ ràng là sai) không nên có bất kỳ ảnh hưởng nào đến việc một chuyển đổi có đang diễn ra hay không. Tôi đã giả định rằng nếu dữ liệu thực sự xấu, thì việc chọn từ chính chế độ xem sẽ tạo ra một lỗi mà nó không có. –

Trả lời

11

Tôi đã gặp phải loại lỗi này trước đây, đó là do "thứ tự các hoạt động" được thực hiện bởi gói thực hiện.

Bạn nhận được thông báo lỗi vì kế hoạch thực hiện cho câu lệnh của bạn (được tạo bởi trình tối ưu hóa) đang thực hiện thao tác CONVERT() trên các hàng có chứa các giá trị chuỗi không thể chuyển đổi thành DATETIME.

Về cơ bản, bạn không có quyền kiểm soát những hàng mà trình tối ưu hóa thực hiện chuyển đổi đó. Bạn biết rằng bạn chỉ cần chuyển đổi được thực hiện trên các hàng nhất định và bạn có các biến vị ngữ (mệnh đề WHERE hoặc ON) loại trừ các hàng đó (giới hạn các hàng cho những hàng cần chuyển đổi), nhưng kế hoạch thực hiện của bạn đang thực hiện thao tác CONVERT() trên các hàng TRƯỚC KHI các hàng đó bị loại trừ.

(Ví dụ, tôi ưu hoa có thể được bầu vào một làm một bảng quét, và thực hiện chuyển đổi trên mỗi hàng, trước khi bất kỳ vị đang được áp dụng.)

tôi không thể đưa ra một câu trả lời cụ thể, mà không một câu hỏi cụ thể và SQL cụ thể tạo ra lỗi.


Một cách tiếp cận đơn giản để giải quyết vấn đề sẽ là sử dụng hàm ISDATE() để kiểm tra xem giá trị chuỗi có thể được chuyển đổi thành ngày hay không.

Đó là, thay thế:

CONVERT(DATETIME,eav.Value) 

với:

CASE WHEN ISDATE(eav.Value) > 0 THEN CONVERT(DATETIME, eav.Value) ELSE NULL END 

hay:

CONVERT(DATETIME, CASE WHEN ISDATE(eav.Value) > 0 THEN eav.Value ELSE NULL END) 

Lưu ý rằng IsDate() chức năng là tùy thuộc vào một số hạn chế đáng kể, chẳng hạn như bị ảnh hưởng bởi cài đặt DATEFORMAT và LANGUAGE của phiên.


Nếu có một số chỉ báo khác trên hàng eav, bạn có thể sử dụng một số thử nghiệm khác, để thực hiện chuyển đổi có điều kiện.

CASE WHEN eav.ValueIsDateTime=1 THEN CONVERT(DATETIME, eav.Value) ELSE NULL END 

Cách tiếp cận khác mà tôi đã sử dụng là để cố gắng đạt được một số lượng ít các kiểm soát trật tự của hoạt động của tôi ưu hoa, sử dụng xem nội tuyến hoặc Common Table Expressions, với các hoạt động mà buộc tôi ưu hoa để thực hiện chúng và áp dụng các vị từ, do đó điều đó xảy ra TRƯỚC KHI bất kỳ chuyển đổi nào trong truy vấn bên ngoài.

+0

Tuyệt vời; nó có vẻ hơi rõ ràng rằng điều này là có thể bây giờ mà bạn đề cập đến nó; mặc dù nó cảm thấy như nó * nên * vật chất hóa các giá trị như là một phần của quan điểm, nó có thể quyết định không. Thay đổi chế độ xem để sử dụng 'ISDATE' như là một phần của phép chiếu đã khắc phục sự cố; cảm ơn! –

+1

+1 nhưng, đối với đoạn cuối cùng của bạn, lưu ý rằng [phương pháp này không phải lúc nào cũng hoạt động] (http://sqlfiddle.com/#!3/0b4c1/1). –

Các vấn đề liên quan