Một phương pháp sẽ là sử dụng một biến thể của
WHERE column = nvl(var, column)
Tuy nhiên, có hai cạm bẫy ở đây:
-
nếu cột là nullable, mệnh đề này sẽ lọc các giá trị null trong khi trong câu hỏi của bạn, bạn sẽ không lọc các giá trị null trong trường hợp thứ hai. Bạn có thể sửa đổi điều khoản này để tính đến giá trị rỗng nhưng nó trở nên xấu xí:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Tất nhiên nếu bằng cách nào đó
impossible_value
khi được chèn vào, bạn sẽ gặp phải một số loại vấn đề (thú vị) khác. - Trình tối ưu hoá không hiểu chính xác loại mệnh đề này. Đôi khi, nó sẽ tạo ra một kế hoạch có ĐOÀN KẾT TẤT CẢ nhưng nếu có nhiều hơn một vài
nvl
, bạn sẽ được quét toàn bộ ngay cả khi có các chỉ mục hoàn toàn hợp lệ.
Đây là lý do tại sao khi có nhiều tham số (ví dụ như một số trường tìm kiếm trong một biểu mẫu lớn), tôi thích sử dụng SQL động:
DECLARE
l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1';
BEGIN
IF param1 IS NOT NULL THEN
l_query := l_query || ' AND column1 = :p1';
ELSE
l_query := l_query || ' AND :p1 IS NULL';
END IF;
/* repeat for each parameter */
...
/* open the cursor dynamically */
OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/;
END;
Bạn cũng có thể sử dụng EXECUTE IMMEDIATE l_query INTO l_result USING param1;