In my scenario, the following query runs fast (0.5 seconds on a table with 70 million rows):
select * from Purchases
where (purchase_id = 1700656396)
and, it even runs fast using bind variables:
var purchase_id number := 1700656396
select * from Purchases
where (purchase_id = :purchase_id)
These run fast because I have an index on the purchase_id
column. (Keep reading...)
I need to create a query that allows "filtering" on arbitrary columns. This means providing several input variables, and filtering on each one unless it is null
. This works fine at first.
For example, the following query runs fast (0.5 seconds), too:
select * from Purchases
where (1700656396 IS NULL OR purchase_id = 1700656396)
and (NULL IS NULL OR purchase_name = NULL)
and (NULL IS NULL OR purchase_price = NULL)
But, when I attempt to parameterize the query, either by bind variables or stored procedure, the query slows down dramatically (1.5 minutes), as if it is ignoring any indexes:
var purchase_id number := 1700656396
var purchase_name varchar2 := NULL
var purchase_price number := NULL
select * from Purchases
where (:purchase_id IS NULL OR purchase_id = :purchase_id)
and (:purchase_name IS NULL OR purchase_name = :purchase_name)
and (:purchase_price IS NULL OR purchase_price = :purchase_price)
Right now, in my application, I am forced to dynamically construct my query at run-time in order to get decent performance. This means I lose all the advantages of parameterized queries, and forces me to worry about SQL injection.
Is it possible to avoid dynamically-constructed queries while still maintaining the same logic?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…