My preferred approach to building complex dynamic queries is:
- Enumerate all the possible queries (i.e. query patterns) that are required. This allows me to see commonalities and find patterns for which generic code can be written.
- Generate each part of the SQL statement separately, then concatenate at the very end. e.g. (this is not meant to be working code, just a sketch of an idea):
<pseudocode>
select_clause = 'SELECT '
from_clause = 'FROM '
where_clause = 'WHERE '
orderby_clause = 'ORDER BY '
if [query on person] then
select_clause += 'p.name, p.dob '
from_clause += 'person p '
orderby_clause += 'p.name '
if [query on address] then
select_clause += 'a.address_text '
from_clause += ', address a '
where_clause += 'p.address_id = a.id AND a.id=:p1 '
else
where_clause += 'p.id=:p1'
end if
end if
sql_stmt = select_clause + from_clause + where_clause + orderby_clause + ';'
</pseudocode>
So, the above code might produce the following statements:
SELECT p.name, p.dob
FROM person p
WHERE p.id=:p1
ORDER BY p.name;
SELECT p.name, p.dob, a.address_text
FROM person p, address a
WHERE p.address_id = a.id AND a.id=:p1
ORDER BY p.name;
With more parameters, this approach means that I don't have to deal with an exponentially-increasing number of possible combinations of criteria.