2008-11-25 40 views
14

Tôi đang tạo một thủ tục lưu sẵn để trả về kết quả tìm kiếm trong đó một số tham số là tùy chọn.Câu lệnh SQL nếu mệnh đề where để tìm kiếm cơ sở dữ liệu

Tôi muốn có "câu lệnh if" trong số của mình, trong đó khoản nhưng không thể làm việc đó. Điều khoản trong đó khoản chỉ nên lọc theo các tham số không null.

Đây là sp

ALTER PROCEDURE spVillaGet 
-- Add the parameters for the stored procedure here 
@accomodationFK int = null, 
@regionFK int = null, 
@arrivalDate datetime, 
@numberOfNights int, 
@sleeps int = null, 
@priceFloor money = null, 
@priceCeil money = null 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

-- Insert statements for procedure here 
select tblVillas.*, tblWeeklyPrices.price from tblVillas 
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK 
where 
    If @accomodationFK <> null then 
     accomodationTypeFK = @accomodationFK 
    @regionFK <> null Then 
     And regionFK = @regionFK 
    IF @sleeps <> null Then 
     And sleeps = @sleeps 
    IF @priceFloor <> null Then 
     And price >= @priceFloor And price <= @priceCeil 


END 

Bất kỳ ý tưởng làm thế nào để làm điều này?

Trả lời

25
select tblVillas.*, tblWeeklyPrices.price 
from tblVillas 
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK 
where (@accomodationFK IS null OR accomodationTypeFK = @accomodationFK) 
    AND (@regionFK IS null or regionFK = @regionFK) 
    AND (@sleeps IS null OR sleeps = @sleeps) 
    AND (@priceFloor IS null OR (price BETWEEN @priceFloor And @priceCeil)) 
+0

cảm ơn sự giúp đỡ của bạn nhưng giá trị trong cơ sở dữ liệu không phải là rỗng. Tôi muốn bỏ qua phần đó của mệnh đề where nếu null được chuyển cho một trong các tham số – mancmanomyst

+4

Tại sao nó hoạt động: nếu @var là null, thì toàn bộ dòng là đúng, bất kể phần còn lại của dòng (do đó bị bỏ qua và không lọc). Nếu nó không phải là null, so với dòng là false * trừ khi * ColVar = @ var, do đó áp dụng bộ lọc. Tôi đã nhầm lẫn lần đầu tiên tôi đọc phong cách bộ lọc này nhưng sử dụng nó ở khắp mọi nơi ngay bây giờ. –

+0

mancmanomyst.myopenid.com: đó là điều này. Tôi đề nghị làm một bảng chân lý - nó không trực quan lúc đầu. –

0

Bạn cũng có thể sử dụng IsNull hoặc chức năng

Where accomodationTypeFK = IsNull(@accomodationFK, accomodationTypeFK) 
    And regionFK = Coalesce(@regionFK,regionFK) 
    And sleeps = IsNull(@sleeps,sleeps) 
    And price Between IsNull(@priceFloor, Price) And IsNull(priceCeil, Price) 

này làm điều tương tự như đề nghị của Michael trên ...

IsNull(), và liên hiệp() làm việc nhiều hay ít liên hiệp theo cùng một cách, họ trả về đối số không Null đầu tiên trong danh sách, ngoại trừ iSNull chỉ cho phép 2 đối số, và Coalesce có thể lấy bất kỳ số ...

http://blogs.msdn.com/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx

+0

Điều này có phá vỡ trình tối ưu hóa hoặc đủ thông minh để thực hiện điều này không? Tôi cảm thấy lo lắng khi thấy những so sánh mùa thu như thế. Tốt đề cập đến, mặc dù. Tôi sử dụng những hàm đó rất nhiều. Một hàm ít được biết hơn là NULLIF (a, b) trả về null nếu a và b bằng nhau. –

+0

Không chắc chắn về trình tối ưu hóa .. dựa vào thực tế là cột ở một bên của toán tử =, vì vậy 'nên' có thể là SARG. Và NullIf() là kewl quá, nhưng tôi không tìm thấy nhiều cơ hội để sử dụng nó ... –

+0

Ditto: Hãy nhận biết rằng mặc dù kỹ thuật này thường được sử dụng, nó có thể có những cạm bẫy đặc biệt là khi có một số lượng lớn các tùy chọn thông số. Do một tìm kiếm SO cho 'tham số sniffing' và 'kế hoạch truy vấn được lưu trữ' –

0

Chúng tôi đã sử dụng rất nhiều COALESCE ở đây trong quá khứ cho "dynamic WHERE clauses" như bạn đang nói đến.

SELECT * 
FROM vehicles 
WHERE ([vin] LIKE COALESCE(@vin, [vin])  + '%' ESCAPE '\') 
    AND ([year] LIKE COALESCE(@year, [year]) + '%' ESCAPE '\') 
    AND ([make] LIKE COALESCE(@make, [make]) + '%' ESCAPE '\') 
    AND ([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\') 

Một vấn đề lớn phát sinh dù khi bạn muốn tùy chọn bộ lọc cho một cột mà cũng nullable ... nếu dữ liệu trong cột là null cho một hàng nhất định và người dùng không nhập bất cứ điều gì để tìm kiếm cho cột đó (do đó người dùng nhập cũng là null), sau đó hàng thậm chí sẽ không hiển thị trong kết quả (trong đó, nếu bộ lọc của bạn là tùy chọn, là hành vi loại trừ không chính xác).

Nhằm bù đắp cho các lĩnh vực nullable, bạn sẽ chỉ phải làm Messier trai SQL như sau:

SELECT * 
FROM vehicles 
WHERE (([vin] LIKE COALESCE(@vin, [vin])  + '%' ESCAPE '\') 
     OR (@vin IS NULL AND [vin] IS NULL)) 
    AND (([year] LIKE COALESCE(@year, [year]) + '%' ESCAPE '\') 
     OR (@year IS NULL AND [year] IS NULL)) 
    AND (([make] LIKE COALESCE(@make, [make]) + '%' ESCAPE '\') 
     OR (@make IS NULL AND [make] IS NULL)) 
    AND (([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\') 
     OR (@model IS NULL AND [model] IS NULL)) 
+0

Như tôi nhớ lại, Đó là một sự khác biệt giữa IsNull và Coalesce ... Một trong số họ (tôi quên đó) trưng bày hành vi này, và khác không .. –

+0

Bây giờ tôi phải tìm kiếm nó ... –

+0

IsNull hoạt động ok ở đây. Coalesce trưng bày vấn đề này. Nhưng bạn cũng có thể giải quyết bằng dàn diễn viên ... http://blogs.msdn.com/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx –

0

Chỉ cần để bạn hiểu, IF là mã thủ tục trong T-SQL. Nó có thể được sử dụng trong một câu lệnh chèn/cập nhật/xóa/chọn nó chỉ có thể được sử dụng để xác định hai câu lệnh mà bạn muốn chạy. Khi bạn cần các khả năng khác nhau trong một câu lệnh, bạn có thể làm như trên hoặc sử dụng một câu lệnh CASE.

-2

Thử đặt câu lệnh IF của bạn xung quanh toàn bộ câu lệnh SQL. Điều đó có nghĩa là sẽ có một câu lệnh SQL cho mỗi điều kiện. Điều đó làm việc cho tôi.

+1

điều này có thể dẫn đến địa ngục của rất nhiều mã trùng lặp. – Duncan

+0

Đồng ý với Duncan. cố gắng làm điều đó trong một thủ tục lưu trữ chấp nhận 6 params .. – Gagan

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