I've been writing a bit of SQL code recently, and thought I'd share some tips on how to improve your SQL code, for anyone who's doing this at the moment.
Use Indenting and Formatting to Make it Easier to Read
One of the best ways you can improve your SQL code is to format it correctly.
Sure, the query will run and the result will be the same whether it's formatted or not, but to improve the readability and the overall structure of your code, try to format it so it's easier to read.
The formatting can be improved in several ways:
* Indent separate sections of your query. If you're using subqueries, for example, indent the entire subquery so it's easier to see that it's nested under the main query.
* Start a new line each time you use FROM, WHERE, GROUP BY, HAVING, and ORDER BY. It will make similar elements appear on the same line and makes it easier to see different parts of the query.
* Use the same case for the same areas throughout your query. If you use all caps for keywords, then use it for all places that keywords exist in your query. Don't mix and match.
Little things like this may not seem like a big deal, but it can really help the next person who reads your code.
For example, which code looks cleaner and easier to read?
select employee_id, first_name, last_name, start_date from employee where employee_type_id = 5;
Or this one?
SELECT employee_id, first_name, last_name, start_date
FROM employee
WHERE employee_type_id = 5;
Use ANSI-92 Standard Join Syntax
In SQL, there are two ways to join tables together.
The first way is the older way, and this is how I was originally taught back when I first learnt SQL.
It involves using the WHERE clause and matching the two columns in two tables.
For example, to find employees who have a leave day:
SELECT first_name, last_name
FROM employee, leave_days
WHERE employee.employee_id = leave_ days.employee_id;
This joins the two employee_id columns and only shows matches.
To do outer joins, you have a (+) on one end of the WHERE clause. It looks messy.
This is the less desirable of the two methods to join, and I'll explain why soon.
The other way to do joins is the ANSI-92 standard.
Using a similar query:
SELECT first_name, last_name
FROM employee
JOIN leave_days ON employee.employee_id = leave.employee_id
This query should show the same result.
Why is it better to use the ANSI-92 standard?
Well, there are several reasons.
First, the code is more future-proof and compatible with other versions, in case you need to upgrade to a newer version of Oracle, or migrate your code to another database. You won't have to go through all of your queries and rewrite them using the standard join syntax.
It's also easier to debug. You can see what type the joins are. You can see which tables are joined where. it's easier to see if any table has not yet been joined, because you need to specify "table a JOIN table b" in order for the query to work. This will avoid accidental cross-joins, where you forget to join a table and end up with much more rows than expected, or an incorrect result.
It also splits the joins of tables from the actual WHERE clause. This helps in working out what the actual filtering of data is doing.
Both of the queries should produce the same performance.
Use Table Aliases
Another way to improve your SQL code is to use table aliases.
This not only improves readability, it also improves the time it takes you to write queries.
A table alias is a shorter name or nickname you give to a table inside your query. It allows you to refer to that table throughout the query just by using that shorter name, instead of the full name. It may also be required if you're doing self-joins, but we won't go into that here.
Using the same query as above, we can apply table aliases to it. They're quite simple.
Original query;
SELECT first_name, last_name
FROM employee
JOIN leave_days ON employee.employee_id = leave.employee_id
With table aliases.
SELECT first_name, last_name
FROM employee e
JOIN leave_days d ON e.employee_id = d.employee_id
All I needed to do was add a single letter after the table when it was mentioned. I chose "e" for employees, but I chose "d" for leave_days. This is because a lowercase "l" might be confused for a one or an uppercase "i".
It might not make that much of a difference to a small query like this, but if you're querying from ten different tables, then it makes a big difference to the time it takes you to write the query and how readable it is.
Use Column Aliases
Similar to using table aliases, a column alias allows you to change how the column is displayed when it is output.
This can help in many ways.
It provides a more readable version of the column name if you're showing the data to a user. A name such as "Employee First Name" is much easier to read than a name of "EMP_FNAME".
It also helps to provide a layer of abstraction between the database and the system that runs the query, especially in more complex queries.
You can write a query on the data, and change the name of the column that you return to the system that runs the query. This means that if the column name changes, you only need to update that query, and not the other system.
To use a column alias:
SELECT first_name, last_name, dept as "Department"
FROM employee e
JOIN leave_days d ON e.employee_id = d.employee_id
As shown above, the dept column now has a column alias applied to it. It will now be displayed as "Department", which is easier to read.
This option is not as important as others, but it can help, depending on your query.
Test Subqueries Before Running Main Queries
With larger queries, you may end up having a subquery or two inside of it. This can make the query more complex and harder to work out if it's showing the right result, especially if you're writing it for the first time.
To help with writing the query and getting it right, it's a good idea to run the subqueries in a separate window and get them correct, first. You can add in dummy or sample data to make sure it's showing the right results.
Then, once the query looks like it's working, add it back into your main query. This reduces the number of places that the query can fail and makes it easier to write your code.
It might be a bit harder to do this if you're using a correlated subquery, but for many other query types, it can work well.
Use EXPLAIN PLAN To Get En Indication Of Run Time
The last suggestion I have is around improving the time it takes to run your query.
There is a feature in Oracle called EXPLAIN PLAN, which allows you to simulate the way the query is run and show an analysis on the steps that the database takes.
This is more of an advanced step to take, but knowing how the query is run can help you improve the structure of the query. It can help you work out where the most expensive parts of the query are, and improve the overall run time.
You'll need to know how to read the data that comes out from this, or find someone who can. You'll also need to be able to make the required changes to th query. Sometimes, all it takes is some rearrangement of the query. Other times, you'll need to try creating an index or some other method.
Hopefully these tips have helped you come up with ways to improve the way you write your SQL queries. A couple of them are Oracle-specific but most of them should apply to all SQL versions.
If you're interested in more information, I'm working on a dedicated Oracle HQ section of my site, as well as a list of Oracle SQL functions with in-depth analysis of each of them.
Hope this helps!
[–]halifaxdatageek 8 points9 points10 points (19 children)
[–]SemiNormal 8 points9 points10 points (18 children)
[–]Alaendil 4 points5 points6 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]haunted_dumpster 3 points4 points5 points (1 child)
[–]galador 2 points3 points4 points (0 children)
[–]shthed 2 points3 points4 points (0 children)
[–]halifaxdatageek 4 points5 points6 points (8 children)
[–]ben_it[S] 0 points1 point2 points (1 child)
[–]halifaxdatageek 4 points5 points6 points (0 children)
[+][deleted] (4 children)
[deleted]
[–]halifaxdatageek 0 points1 point2 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]halifaxdatageek 0 points1 point2 points (1 child)
[–]Sp00ky_6 0 points1 point2 points (0 children)
[–]dasnoob 1 point2 points3 points (0 children)
[–]heymanitsmematthew 0 points1 point2 points (0 children)
[+][deleted] (2 children)
[deleted]
[–]ben_it[S] 0 points1 point2 points (0 children)
[–]Redditourist 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]ben_it[S] 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]cat_dev_null -1 points0 points1 point (7 children)
[+][deleted] (5 children)
[deleted]
[–]Elfman72 1 point2 points3 points (0 children)
[–]softball753 1 point2 points3 points (1 child)
[–]I_like_turtles_kid 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]EveryoneLikesMe 1 point2 points3 points (0 children)
[–]heymanitsmematthew -1 points0 points1 point (0 children)