2011-06-29 41 views
8

Tôi có truy vấn SQL trong SQL Server 2005 đang bị ngắt khi tôi bao gồm thứ tự điều kiện theo. Khi tôi xóa lệnh, truy vấn sẽ hoạt động. Khi tôi viết rõ ràng thứ tự theo điều kiện (ví dụ: order by p.Description) nó hoạt động. Khi tôi bao gồm thứ tự có điều kiện, tôi nhận được lỗi,Thứ tự điều kiện máy chủ SQL theo số

'Conversion failed when converting character string to smalldatetime data type' 

Máy chủ SQL không hiển thị cho tôi dòng mã nào gây ra lỗi này. Tôi tự hỏi làm thế nào tôi có thể sửa lỗi này vì vậy tôi có thể sử dụng thứ tự có điều kiện hoặc khắc phục sự cố cột nào không thành công trong chuyển đổi.

declare @SearchTerm nvarchar(255) 
declare @SortBy nvarchar(255) 
declare @Months int 
declare @VendorID int 
declare @ProductID int 

set @SearchTerm = 'focus' 
set @SortBy = 'product' 
set @Months = 3 
set @VendorID = null 
set @ProductID = null 

-- This makes it so the @Month will filter by n number of months ago. 
declare @PreviousMonths datetime 
if @Months is null 
    begin 
     set @PreviousMonths = 24 
    end 
else 
    begin 
     set @PreviousMonths = DateAdd(month, [email protected], GetDate()) 
    end 

select 
    a.dsAlertID as AlertID, 
    a.ProductID, 
    v.VendorID, 
    p.Description as ProductName, 
    v.LongName as VendorName, 
    a.Introduction, 
    a.Writeup, 
    a.DateAdded 
from 
    ev_ds_Alerts a 
left outer join 
    tblProducts p on a.ProductID = p.ProductID 
left outer join 
    tblVendors v on v.VendorID = p.VendorID 
where 
    (@SearchTerm is null or (a.Writeup like '% ' + @SearchTerm + '%' or a.Introduction like '% ' + @SearchTerm + '%')) 
    and ((@Months is null) or (@Months is not null and a.DateAdded >= @PreviousMonths)) 
    and ((@VendorID is null) or (@VendorID is not null and v.VendorID = @VendorID)) 
    and ((@ProductID is null) or (@ProductID is not null and p.ProductID = @ProductID)) 
order by 
    case @SortBy 
     when 'product' then p.Description 
     when 'vendor' then v.LongName 
     else a.DateAdded 
    end 

-- order by p.Description or v.LongName works when explicitly writing them out! 
+0

Bạn sẽ không eed để sử dụng 'CAST' –

+0

Tạo báo cáo trường hợp độc lập để tránh lỗi truyền dữ liệu kiểu –

Trả lời

15

mỗi câu trả lời trước đó, hãy thử:

order by case @SortBy when 'product' then p.Description when 'vendor' then v.LongName else convert(VARCHAR(25),a.DateAdded,20)

này sẽ cung cấp cho bạn những loại mà bạn muốn, vì nó sẽ định dạng chuỗi ngày hh yyyy-mm-dd: mm: ss.

+1

+1 Tốt đẹp mà bạn nhớ định dạng ngày là yyyy-mm-dd hh: mm: ss để giữ trật tự nhất quán. –

+0

Đây chính xác là những gì tôi cần làm. Cảm ơn bạn rất nhiều! – Halcyon

6

Khi sử dụng một biểu thức CASE trong một ORDER BY - các kiểu dữ liệu trở lại phải luôn luôn giống nhau.

Bạn không thể chọn món anh muốn - INT, DATETIME, VARCHAR, v.v. - không sử dụng SQL động hoặc một số dạng logic quyết định (IE: IF) để chia nhỏ các truy vấn khác nhau.

Trong ví dụ này, bạn có thể sử dụng CAST/CONVERT để thay đổi kiểu dữ liệu DATETIME thành VARCHAR thích hợp. Nhưng trừ khi bạn biết lý do tại sao vấn đề đang xảy ra, bạn có khả năng làm điều đó một lần nữa trong tương lai.

+0

Điều đó có ý nghĩa. Điều gì sẽ là một cách giải quyết thích hợp để sử dụng biểu thức trường hợp? – Halcyon

+0

@Halcyon: Hoặc sử dụng một 'IF' để loại bỏ việc xử lý loại dữ liệu cho các truy vấn riêng biệt hoặc SQL động. –

+0

Giải thích tuyệt vời, nhưng không giải thích cách OP có thể thực hiện thứ tự. Theo @Neil và @gibeath: truyền. –

1

NULL trong danh sách các cột được sắp xếp theo được bỏ qua, vì vậy bạn có thể chia nhỏ chúng theo loại;

ORDER BY 
    CASE 
     WHEN @SortBy = 'product' THEN p.Description 
     WHEN @SortBy = 'vendor' THEN v.LongName 
    END 
    , 
    CASE WHEN @SortBy NOT IN ('product', 'vendor') THEN cda.StartDate END 

Bit xấu cho người khác cuối cùng, tốt hơn nếu bạn có thể;

CASE WHEN @SortBy = '' THEN cda.StartDate END  
+0

Tôi nghĩ bạn có thể xóa trường hợp thứ hai khỏi câu trả lời của mình và chỉ cần thêm StartDate. Trong trường hợp đầu tiên sử dụng một người khác để mặc định không gian. Xem mã của tôi – niktrs

+0

Đúng, sự khác biệt là luôn áp dụng đặt hàng theo ngày (sau lần đặt hàng khác) có thể hoặc không cần thiết –

11

Bạn có thể sử dụng một trường hợp đối với từng loại dữ liệu:

order by 
    case @SortBy 
    when 'product' then p.Description 
    when 'vendor' then v.LongName 
    else '' 
    end, 
    case @SortBy 
    when 'added' then a.DateAdded 
    else '1980-01-01' 
    end 
+0

+1. Tôi đã không nhìn thấy câu trả lời của bạn và tôi đã viết một cái gì đó tương tự – niktrs

0

Nếu bạn quan tâm đến hiệu suất, bạn có thể muốn có một cách tiếp cận khác nhau: 1. Quấn chọn của bạn trong một TVF inline 2. Sử dụng hai CHỌN khác nhau để chúng có thể nhận được hai gói khác nhau, có khả năng hiệu quả hơn so với kế hoạch chung một kích thước phù hợp với tất cả bạn đang nhận ngay bây giờ:

IF @SortBy='product' BEGIN 
    SELECT AlertID, 
(snip) 
    FROM MyTvf 
    ORDER BY Description ; 
    RETURN @@ERROR ; 
END 

IF @SortBy='Vendor' BEGIN 
    SELECT AlertID, 
(snip) 
    FROM MyTvf 
    ORDER BY LongName ; 
    RETURN @@ERROR ; 
END 
+0

Ai downvoted, bạn sẽ chăm sóc để xây dựng? –

+0

Đây là lời khuyên tốt để xem xét. – TTT

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