Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Bỏ qua thông số phạm vi ngày trong mệnh đề where khi thông số không được nhập

Bạn có hai khả năng để tiếp cận các tham số đầu vào tùy chọn.

Đơn giản hơn cách là sử dụng SQL tĩnh và cung cấp mặc định giá trị cho các tham số bị thiếu để bạn nhận được tất cả các kết quả phù hợp.

Ở đây, bạn đơn giản đặt các ranh giới đến DATE tối thiểu và tối đa có thể.

select * 
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between nvl($P{DATE_START},date'1900-01-01') 
                and nvl($P{DATE_END},date'2200-01-01')

Càng nâng cao cách này đã được Tom Kyte phổ biến và dựa trên việc sử dụng SQL động.

Nếu paramaters được cung cấp , bạn tạo SQL bình thường với BETWEEN vị ngữ :

select * 
from customer
where customer_id = $P{CLIENT_ID}
and datetrx between $P{DATE_START} and $P{DATE_END}

Trong trường hợp thiếu thông số (tức là NULL được thông qua) bạn tạo một SQL khác như hình bên dưới.

select * 
from customer
where customer_id = $P{CLIENT_ID}
and (1=1 or datetrx between $P{DATE_START} and $P{DATE_END})

Lưu ý rằng

1) số lượng biến liên kết giống nhau trong cả hai biến thể của truy vấn, điều này quan trọng là bạn có thể sử dụng setXXXX giống hệt nhau tuyên bố

2) do phím tắt 1 = 1 orbetween vị ngữ bị bỏ qua, tức là tất cả các ngày đều được xem xét.

Tùy chọn nào nên được sử dụng?

Đối với các truy vấn đơn giản sẽ có sự khác biệt nhỏ, nhưng đối với các truy vấn phức tạp với một số tùy chọn thiếu tham số và dữ liệu lớn, thì phương pháp tiếp cận SQL động được ưu tiên hơn .

Lý do là, bằng cách sử dụng SQL tĩnh, bạn sử dụng cùng một câu lệnh cho nhiều truy vấn khác nhau - đây là câu lệnh dành cho truy cập with phạm vi dữ liệu và một để truy cập không có phạm vi dữ liệu.

Tùy chọn động tạo ra các SQL khác nhau cho mỗi quyền truy cập.

Bạn có thể thấy nó trên các kế hoạch thực hiện:

Truy cập với phạm vi ngày

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |     1 |    22 |     1   (0)| 00:00:01 |
|*  1 |  FILTER           |           |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| CUST_IDX1 |     1 |    22 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_DATE(:1)<=TO_DATE(:2))
   2 - access("CUSTOMER_ID"=1 AND "DATETRX">=:1 AND "DATETRX"<=:2)

Truy cập không có dải dữ liệu

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |     1 |    22 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| CUST_IDX1 |     1 |    22 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("CUSTOMER_ID"=1)

Cả hai câu lệnh đều tạo ra kế hoạch thực thi khác nhau, được tối ưu hóa cho tham số đầu vào. Trong tùy chọn tĩnh, việc sử dụng phải chia sẻ cùng một kế hoạch thực thi cho tất cả đầu vào có thể gây ra sự cố.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Khóa duy nhất trong Oracle với các ví dụ

  2. Oracle ORA-00979 - không phải là biểu thức GROUP BY

  3. Ví dụ về mệnh đề WHEN của Oracle Trigger

  4. Làm cách nào để tạo mệnh đề WHERE động?

  5. Cách xác định kích thước bảng trong Oracle