SQL style guide by Simon Holywell
sqlstyle.guide
sqlstyle.guide
SELECT file_hash
FROM file_system
WHERE file_name = '.vimrc';
This style is annoying and I wish it gained less traction. It looks neat but it puts so much burden on the query writer, especially when you modify the query and all of the sudden you need to indent multiple lines just to make them all align. You know what's neat and still easy to modify/diff? Just indent a new line for each row. SELECT
file_hash
FROM
file_system
WHERE
file_name = '.vimrc';Editors highlight syntax.
edit: Not the editor I use but thought it might be helpful. Here is an extension, which I haven't tested, to do this in VSCode: https://marketplace.visualstudio.com/items?itemName=iuyoy.hi...
```sql
```
And 10 other dialects are listed..
And people who use things like Datagrip or other IDEs will probably format with their IDE's preferences unless there is a plugin for things like pgFormatter. This works well if there is a company mandated editor/IDE, but not so well when you have developers across various editors and IDEs.
With CTEs you can offload sophisticated joins and constraints in such a way that less experienced developers can follow behind more easily.
Once you find multiple queries using the same WITH clauses, you can create more permanent views that further centralize and optimize these concerns.
I ended up manually overloading get_extra_restriction on a custom ForeignKey class (we couldn't use FilteredRelation b/c we were still on django 1.11), which ensured that the JOIN ON ... clause limited the tables being joined to their correct partition/schema while being accessed through a view
The view thing is a long story — it was a legacy PAC codebase from the '90s which used 13+ schemas in a mysql db that was then being synced to our postgres db through Amazon DMS. All of the tables on each view contain identical source_schema/CompanyID columns, hence the
'%(remote_alias)s. "source_schema" = %(fk_alias)s. "source_schema" AND '
'%(remote_alias)s. "CompanyID" = %(fk_alias)s. "CompanyID"
etc. approachbefore/after query plan in depesz: https://imgur.com/a/HQbNSIL
As an aside why not use postgres's mysql foreign data wrapper instead of syncing with the mysql database?
To directly answer your question, though, without going into too much detail, there were pci compliance issues with some tables/columns in the mysql db, so if I had to guess, perhaps DMS had the capability to assuage that concern more elegantly than mysql_fdw[0], though the mysql_fwd EXCEPT parameter seems to also do the same thing, so honestly, I have no idea.
By default, all views and tables existing in a particular database on the MySQL host are imported. Using this option, you can exclude specified foreign tables from the import.[1]
[0]: https://github.com/EnterpriseDB/mysql_fdw[1]: https://www.enterprisedb.com/docs/mysql_data_adapter/latest/...
Hard disagree here. "Let's do/not do this, in case we decide to change databases in the future" is one of the greatest lies we tell ourselves. You're just making your life harder now and in the near future, for the nebulous promise of "seamlessly replacing your database backend if needed".
In 95% of cases, it's not needed, and you're getting all of the downsides for no benefit. And if it's needed in a late stage of your application's life, changing a bunch of SQL functions will be just one tiny problem among many bigger ones.
It also achieves that in monochrome, which is likely to be the case when an SQL query is in a shell script's <<< HEREDOC or in a string blob in a log file or source code for another language's compiler.
It looks so much cleaner in my eyes.
Plus it uses constant-sized indents, which means less futzing about with spaces and all that.
Also means you can comment out the first select item, something you can't do with the article's approach.
And this stacks much better once you start doing complex joins especially when you can add parentheses to change where you actually join
FROM a JOIN b JOIN c
Can be different than FROM a JOIN (b JOIN C)
Apart from that I think I came up independently to the exact same rules when building the prettier extension for SQL a few years back.Your DB's query planner should optimise given the available indices.
It’s still highly readable but also much much easier to write and modify.
Though I am biased because it’s also how I used to write SQL back when PL/SQL was my day job. Albeit I fell into this design because it proved to be the easiest way to write and maintain readable code.
2018 (59 points, 16 comments) https://news.ycombinator.com/item?id=17924917
2016 (257 points, 147 comments) https://news.ycombinator.com/item?id=12671667
2015 (16 points, 10 comments) https://news.ycombinator.com/item?id=9941150
IMO, reading “SELECT employee.first_name” makes much more sense than “SELECT staff.first_name”.
join users as user on user….
Then do as you please without the that if you are dealing with a user or leave it plural if multiple…
And if we’re talking personal preference I really dislike caps in reserved words in sql, even before highlighting was everywhere it still just feels archaic for no good reason
SELECT employee.name where role = 'developer'
Vs
SELECT staff.name” where role = 'developer'
Then the plural one reads better
SELECT employee.Name
FROM employee
WHERE employee.Role = 'developer'
reads much better to me than SELECT employees.Name
FROM employees
WHERE employees.Role = 'developer'I also think the advice around join table naming is a bit silly. Calling a join table between `cars` and `mechanics` `services` (rather than `cars_mechanics`) does not make the relationship clearer, and only works when the relationships maps to a the real world where the relationship has a commonly used name.
The more I read of this guide, the uglier the SQL is.
select e.first_name,
e.last_name,
s.amount
from employee as e
inner join salary as s
on e.id = s.employee_id;I've found the opposite true in my limited experience, at least when doing any sort of ORM, then having id implicitly as the primary key makes life so much easier.
Seems like a lot of work to me. And I don't know any formatter that'd do that work.
I do agree it makes joins more verbose.
Please don't prefix the main table id with the table name.
I also use "id" but I would say SQL was designed with the opinion that ids should be prefixed with the table name.
I know it is a matter of discipline but any tool that encourages consistency helps. A database schema is definitely one of those tools.
One unrelated idea is to include the entity in the id itself. I have never done this but I’d imagine it would help with things like logging / observability. It would not play nice with indices though.
From this style guide, the aliases section would look like this in my style guide:
SELECT first_name
FROM staff
JOIN students
ON students.mentor_id = staff.staff_num;I'm not opposed to aliases, it's just no longer something I do by default.
Also aliasing can be as much for legibility as anything.
SELECT
ZZ.first_name
FROM staff AS ZZ
INNER JOIN students AS Q ON Q.mentor_id = ZZ.staff_num; SELECT
staff.first_name
FROM staff
INNER JOIN students ON student.mentor_id = staff.staff_num;
Whether or not you agree on the exact number [0], humans have limited working memory and aliases that don't group up concepts use it up unnecessarily.[0] https://en.m.wikipedia.org/wiki/The_Magical_Number_Seven,_Pl...
Aliases are the SQL equivalent of ternary operators. Are you trying to write clean code or are you trying to express to other people you know things?
It's common to have endpoints like `/customers` and `/customers/{id}` which has a tendency to move SQL table names to match the API endpoint.
I tend to name tables in the singular form if writing applications that interact directly with SQL tables, but where standing up a API in front of a SQL database, I tend to move to the plural naming of the table.
It helps to have the table 'customers' be associated with an API endpoint of the same name.
Shifts my focus away from the rest of the query.
Just like I don’t like uppercase paragraphs because of the same reason
Are you writing C code that's portable to Java, C++ an C#?
No that would be stupid. Same here. Any heavy loaded, heavily used db is going toneed optimization sober or later.
The In vs Or is dumb bc ORs blow up query plans and your better off with unions instead.