Query Writing / Tuning Guidelines


  • The query should be written in upper case however, the constant / hard coded values can be in lower case.
  • Single space should be used between the query clauses and after comma. It should also be between column / table names in select, from, group by or order by clauses.
  • To make SQL Statements more readable, start each clause on a new line and indent when needed. Following is an example:

    SELECT TITLE_ID, TITLE
    FROM TITLES
    WHERE TITLE = 'Computer’
    • Sub queries must be also be indented such that they can be identified from the main query.
  • Use column names instead of asterisk (*) , even if all the columns are required.
  • Query must use alias names (instead of using table name or not using table name) for referencing column name however; single table query can be an exception.
  • Avoid using DISTINCT keyword as much as possible.
  • Always convert the constant to match the table column.
    • Do not use trunc(), to_char(), upper(), lower() etc. functions on the table columns in the where clause.
  • Avoid using UNION at all however, if required, use as minimum (sets of UNION) as possible in a single query and use instead UNION ALL (UNION ALL can only be used where resultant queries will return disjoint sets - most of the time this is the case).
  • Use minimum table joins and always ensure that there exist n-1 joins in a query in addition to other filter criteria.
  • Avoid using ORDER BY / GROUP BY clause until warranted for.
  • Like operator match should only be used when required and wild card should also be used with caution and limited as per requirement (avoid using wild card on both sides of the value).
  • Do not forget to use separator brackets especially when using OR operator however, unnecessary use of brackets should be avoided.
  • Use conjunctive form instead of disjunctive form - use AND and IN instead of OR or NOT IN.
  • Try your level best to write query which is in compliance with ANSI-92 SQL standards.
  • Write comments in your stored procedures, triggers and SQL batches generously, whenever something is not very obvious. This helps other programmers understand your code clearly. Don't worry about the length of the comments, as it won't impact the performance, unlike interpreted languages like ASP 2.0.
  • Try to avoid server side cursors as much as possible. Always stick to a 'set-based approach' instead of a 'procedural approach' for accessing and manipulating data. Cursors can often be avoided by using SELECT statements instead.
  • Every table must have a primary or unique key.
  • If you have a choice, do not store binary or image files (Binary Large Objects or BLOBs) inside the database. Instead, store the path to the binary or image file in the database and use that as a pointer to the actual binary file stored elsewhere on a server. Retrieving and manipulating these large binary files is better performed outside the database, and after all, a database is not meant for storing files.
  • Always use a column list in your INSERT statements. This helps in avoiding problems when the table structure changes (like adding or dropping a column). Here's an example which shows the problem.
  • Perform all your referential integrity checks and data validations using constraints (foreign key and check constraints) instead of triggers, as they are faster. Limit the use triggers only for auditing, custom tasks and validations that can not be performed using constraints. Constraints save you time as well, as you don't have to write code for these validations, allowing the RDBMS to do all the work for you.
  • Always access tables in the same order, this helps in avoiding deadlocks. Other things to keep in mind to avoid deadlocks are: Keep your transactions as short as possible. Touch as few data as possible during a transaction. Never, ever wait for user input in the middle of a transaction. Do not use higher level locking hints or restrictive isolation levels unless they are absolutely needed. Make your front-end applications deadlock-intelligent, that is, these applications should be able to resubmit the transaction incase the previous transaction fails. In your applications, process all the results returned by database server immediately so that the locks on the processed rows are released, hence no blocking.
  • Offload tasks, like string manipulations, concatenations, row numbering, case conversions, type conversions etc., to the front-end applications if these operations are going to consume more CPU cycles on the database server. Also try to do basic validations in the front-end itself during data entry. This saves unnecessary network roundtrips.
  • SQL Server: Always check the global variable @@ERROR immediately after executing a data manipulation statement (like INSERT/UPDATE/DELETE), so that you can rollback the transaction in case of an error (@@ERROR will be greater than 0 in case of an error). This is important, because, by default, SQL Server will not rollback all the previous changes within a transaction if a particular statement fails. This behavior can be changed by executing SET XACT_ABORT ON. The @@ROWCOUNT variable also plays an important role in determining how many rows were affected by a previous data manipulation (also, retrieval) statement, and based on that you could choose to commit or rollback a particular transaction.
  • Using variables instead of constant values within your queries improves readability and maintainability of your code. Consider the following example:

    SELECT OrderID, OrderDate
    FROM Orders
    WHERE OrderStatus IN (5,6)

    The same query can be re-written in a mode readable form as shown below:

    DECLARE @ORDER_DELIVERED, @ORDER_PENDING
    SELECT @ORDER_DELIVERED = 5, @ORDER_PENDING = 6

    SELECT OrderID, OrderDate
    FROM Orders
    WHERE OrderStatus IN (@ORDER_DELIVERED, @ORDER_PENDING)

Note: These tips apply for all queries used in Trigger, Procedures, Views etc.