Writing Better Dynamic SQL

Dynamic SQL is a powerful tool. In its proper place it can achieve quite a bit of work in a relatively small amount of code. Used improperly, however, it can cause all sorts of code maintenance headaches. Consider the following procedure. It uses the HR schema and sample data that comes with an installation of the Oracle database: CREATE OR

Dynamic SQL is a powerful tool. In its proper place it can achieve quite a bit of work in a relatively small amount of code. Used improperly, however, it can cause all sorts of code maintenance headaches.

Consider the following procedure. It uses the HR schema and sample data that comes with an installation of the Oracle database:

Since dynamic queries are not parsed until run-time, it behoves us to write as little SQL as possible to avoid bugs in the code. I’ve seen dynamic query strings that ran for hundreds of lines with several joins, unions, aggregations, and parameter values hard-coded into the string (we all know better than to do that unless (a) there’s an extremely compelling reason and (b) we check for SQL injection attacks, right?). The more involved our SQL is, especially if our code conditionally adds clauses to the query, the greater likelihood for a typographical error in SQL that we may or may not come across in our testing.

The query in SEARCH_EMPLOYEES has several joins, aliases some columns, and concatenates some columns with blank spaces, necessitating some escaped single-quotes in the middle of our string (lines 11 and 20). This example query string is not too bad, but we’ll use it to illustrate a coding strategy that can do a lot to simplify our code development and maintenance.

First, we’ll define a view to handle the joins, column transformations, and aliasing. We want as much work as possible performed by the view so that the procedure only selects and filters–nothing more:

Next, we’ll rewrite our stored procedure:

Notice how much tidier the query is in this procedure. We’ve reduced the amount of text in the string by moving much of the SQL heavy-lifting into a view, reducing our risk of typoes. We’ve defined the parameters to be typed by columns in the SEARCH_EMPLOYEES_VIEW, which creates a hard dependency between the procedure and the view. The prior version of this procedure had no hard dependencies. One could drop an underlying table with impunity–until the procedure was called. With the new version of the query an alteration of the underlying view would invalidate the procedure, alerting us to the fact that a code object has been impacted by the schema change.