2009-03-30 32 views
30

Tôi có một biểu mẫu nơi người dùng có thể chỉ định các thông số khác nhau để tìm hiểu một số dữ liệu (trạng thái, ngày, v.v ...).Thủ tục được lưu trữ với các tham số "WHERE" tùy chọn

tôi có thể tạo ra một truy vấn đó là:

SELECT * FROM table WHERE: 
status_id = 3 
date = <some date> 
other_parameter = <value> 

vv Mỗi WHERE là tùy chọn (tôi có thể chọn tất cả các hàng với status = 3, hoặc tất cả các hàng với date = 10/10/1980, hoặc tất cả các hàng với status = 3 AND date = 10/10/1980, vv).

Với số lượng lớn tham số, tất cả tùy chọn, cách tốt nhất để tạo nên một quy trình được lưu động là gì?

Tôi đang làm việc trên nhiều DB khác nhau, chẳng hạn như: MySQL, Oracle và SQLServer.

Trả lời

44

Một trong những cách dễ nhất để thực hiện điều này:

SELECT * FROM table 
WHERE ((@status_id is null) or (status_id = @status_id)) 
and ((@date is null) or ([date] = @date)) 
and ((@other_parameter is null) or (other_parameter = @other_parameter)) 

, vv này hoàn toàn loại bỏ sql năng động và cho phép bạn tìm kiếm trên một hoặc nhiều lĩnh vực. Bằng cách loại bỏ sql động, bạn loại bỏ một mối quan tâm bảo mật khác về tiêm sql.

+2

Điều này không cho phép tất cả các thông số là tùy chọn. Trong ví dụ này @status_id phải được chuyển vào. Ngay cả khi nó là null, bạn phải vượt qua null để thực hiện điều này. – Eppz

+0

Bạn có thể cung cấp một giá trị mặc định cho các tham số trong MS SQL Server. Tôi không biết về MySQL –

+4

Chỉ cần ghi nhớ rằng tùy thuộc vào RDBMS của bạn và làm thế nào nó lưu trữ các kế hoạch truy vấn, bạn có thể không nhận được hiệu suất tốt nhất có thể với phương pháp này. –

3

Bạn có thể làm một cái gì đó giống như

WHERE 
(
ParameterA == 4 OR ParameterA IS NULL 
) 

AND 
(
ParameterB == 12 OR ParameterB IS NULL 
) 
11

Tạo thủ tục của bạn như thế này:

CREATE PROCEDURE [dbo].[spXXX] 
    @fromDate datetime = null, 
    @toDate datetime = null, 
    @subCode int = null 
as 
begin 
set NOCOUNT ON 
/* NOCOUNT limits the server feedback on select results record count */ 
SELECT 
    fields... 
FROM 
    source 
WHERE 
    1=1 
--Dynamic where clause for various parameters which may or may not be passed in. 
and (@fromDate is null or [dateField] >= @fromDate) 
and (@toDate is null or [dateField] <= @toDate) 
and (@subCode is null or subCode= @leaveTypeSubCode) 
order by fields... 

này sẽ cho phép bạn thực hiện các thủ tục với 0 params, tất cả các params, hoặc bất kỳ # của params.

1

Nếu bạn muốn tránh tự động xây dựng chuỗi SQL (thường tránh nhất), bạn có thể thực hiện việc này bằng cách so sánh từng tiêu chí trong vị trí của bạn với giá trị mặc định, tương đương với "bỏ qua". Ví dụ:

select * from Table where 
    (@Col1 IS NULL OR Col1 = @Col1) /*If you don't want to filter in @col, pass in NULL*/ 
    AND 
    (@Col2 IS NULL OR Col2 = @Col2) 
4

Đây là phong cách tôi sử dụng:

t-sql

SELECT *   
FROM table   
WHERE  
status_id = isnull(@status_id ,status_id)  
and date = isnull(@date ,date)  
and other_parameter = isnull(@other_parameter,other_parameter) 

oracle

SELECT *   
FROM table   
WHERE  
status_id = nval(p_status_id ,status_id)  
and date = nval(p_date ,date)  
and other_parameter = nval(p_other_parameter,other_parameter) 
2

Một cách có thể đọc được và duy trì để làm điều đó (thậm chí có thể sử dụng với JOIN/APPLY):

where 
     (@parameter1 IS NULL OR your_condition1) 
    and (@parameter2 IS NULL OR your_condition2) 
-- etc 

Tuy nhiên đó là một ý tưởng tồi trên hầu hết các bảng lớn (thậm chí nhiều hơn sử dụng THAM GIA/ÁP DỤNG), kể từ khi thực hiện kế hoạch của bạn sẽ không bỏ qua các giá trị NULL và tạo ra hiệu suất kẽ hở lớn (ví dụ: scaning tất cả một bảng tìm kiếm các giá trị NULL).

Cách xoay vòng trong SQL Server là sử dụng tùy chọn WITH (RECOMPILE) trong truy vấn của bạn (có sẵn từ SQL 2008 SP1 CU5 (10.0.2746)).

Cách tốt nhất để thực hiện điều này (hiệu suất khôn ngoan) là sử dụng IF ... khối ELSE, một cho mỗi kết hợp có thể. Có lẽ nó mệt mỏi nhưng bạn sẽ có màn trình diễn tốt nhất và không quan trọng cài đặt cơ sở dữ liệu của bạn.

Nếu bạn cần thêm chi tiết, bạn có thể tìm KM. trả lời here.

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