1
0
Fork 0
mirror of https://github.com/treffynnon/sqlstyle.guide.git synced 2025-03-09 12:49:51 -05:00

Update sqlstyle.guide.md

initial update for my taste and SQL Server
This commit is contained in:
Wes Brown 2017-01-04 16:53:52 -06:00 committed by GitHub
parent 89421d340e
commit 981e802e86

View file

@ -16,7 +16,7 @@ It is easy to include this guide in [Markdown format][dl-md] as a part of a
project's code base or reference it here for anyone on the project to freely
read—much harder with a physical book.
SQL style guide by [Simon Holywell][simon] is licensed under a [Creative Commons
The origional SQL style guide by [Simon Holywell][simon] is licensed under a [Creative Commons
Attribution-ShareAlike 4.0 International License][licence].
Based on a work at [http://www.sqlstyle.guide][self].
@ -28,8 +28,6 @@ Based on a work at [http://www.sqlstyle.guide][self].
* Make judicious use of white space and indentation to make code easier to read.
* Store [ISO-8601][iso-8601] compliant time and date information
(`YYYY-MM-DD HH:MM:SS.SSSSS`).
* Try to use only standard SQL functions instead of vendor specific functions for
reasons of portability.
* Keep code succinct and devoid of redundant SQL—such as unnecessary quoting or
parentheses or `WHERE` clauses that can otherwise be derived.
* Include comments in SQL code where necessary. Use the C style opening `/*` and
@ -37,16 +35,22 @@ Based on a work at [http://www.sqlstyle.guide][self].
them with a new line.
```sql
SELECT file_hash -- stored ssdeep hash
FROM file_system
WHERE file_name = '.vimrc';
SELECT
file_hash -- stored ssdeep hash
FROM
file_system
WHERE
file_name = '.vimrc';
```
```sql
/* Updating the file record after writing to the file */
UPDATE file_system
SET file_modified_date = '1980-02-22 13:19:01.00000',
file_size = 209732
WHERE file_name = '.vimrc';
UPDATE
file_system
SET
file_modified_date = '1980-02-22 13:19:01.00000',
file_size = 209732
WHERE
file_name = '.vimrc';
```
### Avoid
@ -55,9 +59,7 @@ UPDATE file_system
* Descriptive prefixes or Hungarian notation such as `sp_` or `tbl`.
* Plurals—use the more natural collective term where possible instead. For example
`staff` instead of `employees` or `people` instead of `individuals`.
* Quoted identifiers—if you must use them then stick to SQL92 double quotes for
portability (you may need to configure your SQL server to support this depending
on vendor).
* Quoted identifiers—if you must use them then stick to SQL Server's [] instead of SET QUOTED_IDENTIFIER ON to escape reserved words or words with invalid characters in them.
* Object oriented design principles should not be applied to SQL or database
structures.
@ -78,8 +80,10 @@ UPDATE file_system
understood.
```sql
SELECT first_name
FROM staff;
SELECT
first_name
FROM
staff;
```
### Tables
@ -110,14 +114,20 @@ SELECT first_name
a column defined in the schema.
```sql
SELECT first_name AS fn
FROM staff AS s1
JOIN students AS s2
ON s2.mentor_id = s1.staff_num;
SELECT
first_name AS fn
FROM
staff AS s1
INNER JOIN
students AS s2
ON
s2.mentor_id = s1.staff_num;
```
```sql
SELECT SUM(s.monitor_tally) AS monitor_total
FROM staff AS s;
SELECT
SUM(s.monitor_tally) AS monitor_total
FROM
staff AS s;
```
### Stored procedures
@ -154,13 +164,33 @@ like `SELECT` and `WHERE`.
It is best to avoid the abbreviated keywords and use the full length ones where
available (prefer `ABSOLUTE` to `ABS`).
Do not use database server specific keywords where an ANSI SQL keyword already
exists performing the same function. This helps to make code more portable.
Do not user SQL ANSI 89 syntax anywhere even if the resulting query returns the
same results to cut down on confusion and keep the code intent clear
```sql
SELECT model_num
FROM phones AS p
WHERE p.release_date > '2014-09-30';
SELECT
a.person_id,
b.address_id,
b.address_1
FROM
person a, address b
where
a.person_id = b.address_id
```
Instead favor SQL ANSI 92
```sql
SELECT
a.person_id,
b.address_id,
b.address_1
FROM
person a
INNER JOIN
address b
on
a.person_id = b.address_id
```
### White space
@ -170,21 +200,23 @@ spacing is used. Do not crowd code or remove natural language spaces.
#### Spaces
Spaces should be used to line up the code so that the root keywords all end on
the same character boundary. This forms a river down the middle making it easy for
the readers eye to scan over the code and separate the keywords from the
implementation detail. Rivers are [bad in typography][rivers], but helpful here.
Spaces should be used to line up the code so that the root keywords all start on
the same character boundary.
```sql
SELECT f.average_height, f.average_diameter
FROM flora AS f
WHERE f.species_name = 'Banksia'
OR f.species_name = 'Sheoak'
OR f.species_name = 'Wattle';
SELECT
f.average_height, f.average_diameter
FROM
flora AS f
WHERE
f.species_name = 'Banksia'
OR
f.species_name = 'Sheoak'
OR
f.species_name = 'Wattle';
```
Notice that `SELECT`, `FROM`, etc. are all right aligned while the actual column
names and implementation specific details are left aligned.
Notice that `SELECT`, `FROM`, etc. are all left aligned and are on their own line.
Although not exhaustive always include spaces:
@ -194,10 +226,16 @@ Although not exhaustive always include spaces:
comma or semicolon.
```sql
SELECT a.title, a.release_date, a.recording_date
FROM albums AS a
WHERE a.title = 'Charcoal Lane'
OR a.title = 'The New Danger';
SELECT
a.title,
a.release_date,
a.recording_date
FROM
albums AS a
WHERE
a.title = 'Charcoal Lane'
OR
a.title = 'The New Danger';
```
#### Line spacing
@ -216,23 +254,32 @@ creates a uniform gap down the middle of query. It makes it much easier to scan
the query definition over quickly too.
```sql
INSERT INTO albums (title, release_date, recording_date)
VALUES ('Charcoal Lane', '1990-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000'),
('The New Danger', '2008-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000');
INSERT INTO
albums (title, release_date, recording_date)
VALUES
('Charcoal Lane', '1990-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000'),
('The New Danger', '2008-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000');
```
```sql
UPDATE albums
SET release_date = '1990-01-01 01:01:01.00000'
WHERE title = 'The New Danger';
UPDATE
albums
SET
release_date = '1990-01-01 01:01:01.00000'
WHERE
title = 'The New Danger';
```
```sql
SELECT a.title,
a.release_date, a.recording_date, a.production_date -- grouped dates together
FROM albums AS a
WHERE a.title = 'Charcoal Lane'
OR a.title = 'The New Danger';
SELECT
a.title,
a.release_date, a.recording_date, a.production_date -- grouped dates together
FROM
albums AS a
WHERE
a.title = 'Charcoal Lane'
OR
a.title = 'The New Danger';
```
### Indentation
@ -242,40 +289,58 @@ are followed.
#### Joins
Joins should be indented to the other side of the river and grouped with a new
line where necessary.
Joins should follow the same indentation as normal.
Again, fully expand key words prefer INNER JOIN over JOIN.
```sql
SELECT r.last_name
FROM riders AS r
INNER JOIN bikes AS b
ON r.bike_vin_num = b.vin_num
AND b.engines > 2
INNER JOIN crew AS c
ON r.crew_chief_last_name = c.last_name
AND c.chief = 'Y';
SELECT
r.last_name
FROM
riders AS r
INNER JOIN
bikes AS b
ON
r.bike_vin_num = b.vin_num
AND
b.engines > 2
INNER JOIN
crew AS c
ON
r.crew_chief_last_name = c.last_name
AND
c.chief = 'Y';
```
#### Subqueries
Subqueries should also be aligned to the right side of the river and then laid
out using the same style as any other query. Sometimes it will make sense to have
the closing parenthesis on a new line at the same character position as it's
opening partner—this is especially true where you have nested subqueries.
Subqueries should follow the same alignment rules with the query beginning on the line after the open parenthesis.
```sql
SELECT r.last_name,
(SELECT MAX(YEAR(championship_date))
FROM champions AS c
WHERE c.last_name = r.last_name
AND c.confirmed = 'Y') AS last_championship_year
FROM riders AS r
WHERE r.last_name IN
(SELECT c.last_name
FROM champions AS c
WHERE YEAR(championship_date) > '2008'
AND c.confirmed = 'Y');
SELECT
r.last_name,
(
SELECT
MAX(YEAR(championship_date))
FROM
champions AS c
WHERE
c.last_name = r.last_name
AND
c.confirmed = 'Y'
) AS last_championship_year
FROM
riders AS r
WHERE
r.last_name IN
(
SELECT
c.last_name
FROM
champions AS c
WHERE
YEAR(championship_date) > '2008'
AND
c.confirmed = 'Y'
);
```
### Preferred formalisms
@ -290,14 +355,19 @@ SELECT r.last_name,
likely should be.
```sql
SELECT CASE postcode
WHEN 'BN1' THEN 'Brighton'
WHEN 'EH1' THEN 'Edinburgh'
END AS city
FROM office_locations
WHERE country = 'United Kingdom'
AND opening_time BETWEEN 8 AND 9
AND postcode IN ('EH1', 'BN1', 'NN1', 'KW1')
SELECT
CASE postcode
WHEN 'BN1' THEN 'Brighton'
WHEN 'EH1' THEN 'Edinburgh'
END AS city
FROM
office_locations
WHERE
country = 'United Kingdom'
AND
opening_time BETWEEN 8 AND 9
AND
postcode IN ('EH1', 'BN1', 'NN1', 'KW1')
```
## Create syntax
@ -310,8 +380,6 @@ Indent column definitions by four (4) spaces within the `CREATE` definition.
### Choosing data types
* Where possible do not use vendor specific data types—these are not portable and
may not be available in older versions of the same vendor's software.
* Only use `REAL` or `FLOAT` types where it is strictly necessary for floating
point mathematics otherwise prefer `NUMERIC` and `DECIMAL` at all times. Floating
point rounding errors are a nuisance!
@ -354,6 +422,7 @@ constraints along with field value validation.
##### General
* Tables must have at least one key to be complete and useful.
* This key should be made the clustered index unless there is a more suitable candidate.
* Constraints should be given a custom name excepting `UNIQUE`, `PRIMARY KEY`
and `FOREIGN KEY` where the database vendor will generally supply sufficiently
intelligible names automatically.
@ -411,13 +480,15 @@ CREATE TABLE staff (
concerns such as time-based archiving or location in a multi-national
organisation. Later queries must then work across multiple tables with `UNION`
rather than just simply querying one table.
Prefer table partitioning if possible.
## Appendix
### Reserved keyword reference
A list of ANSI SQL (92, 99 and 2003), MySQL 3 to 5.x, PostgreSQL 8.1, MS SQL Server 2000, MS ODBC and Oracle 10.2 reserved keywords.
A list of SQL Server 2008 and above reserved keywords.
[Reserved Keywords] [sql-server-reserved-keywords]
```sql
A
@ -1209,65 +1280,214 @@ UTC_DATE
UTC_TIME
UTC_TIMESTAMP
VACUUM
VALID
VALIDATE
VALIDATOR
VALUE
ADD
ALL
ALTER
AND
ANY
AS
ASC
AUTHORIZATION
BACKUP
BEGIN
BETWEEN
BREAK
BROWSE
BULK
BY
CASCADE
CASE
CHECK
CHECKPOINT
CLOSE
CLUSTERED
COALESCE
COLLATE
COLUMN
COMMIT
COMPUTE
CONSTRAINT
CONTAINS
CONTAINSTABLE
CONTINUE
CONVERT
CREATE
CROSS
CURRENT
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_USER
CURSOR
DATABASE
DBCC
DEALLOCATE
DECLARE
DEFAULT
DELETE
DENY
DESC
DISK
DISTINCT
DISTRIBUTED
DOUBLE
DROP
DUMP
ELSE
END
ERRLVL
ESCAPE
EXCEPT
EXEC
EXECUTE
EXISTS
EXIT
EXTERNAL
FETCH
FILE
FILLFACTOR
FOR
FOREIGN
FREETEXT
FREETEXTTABLE
FROM
FULL
FUNCTION
GOTO
GRANT
GROUP
HAVING
HOLDLOCK
IDENTITY
IDENTITY_INSERT
IDENTITYCOL
IF
IN
INDEX
INNER
INSERT
INTERSECT
INTO
IS
JOIN
KEY
KILL
LEFT
LIKE
LINENO
LOAD
MERGE
NATIONAL
NOCHECK
NONCLUSTERED
NOT
NULL
NULLIF
OF
OFF
OFFSETS
ON
OPEN
OPENDATASOURCE
OPENQUERY
OPENROWSET
OPENXML
OPTION
OR
ORDER
OUTER
OVER
PERCENT
PIVOT
PLAN
PRECISION
PRIMARY
PRINT
PROC
PROCEDURE
PUBLIC
RAISERROR
READ
READTEXT
RECONFIGURE
REFERENCES
REPLICATION
RESTORE
RESTRICT
RETURN
REVERT
REVOKE
RIGHT
ROLLBACK
ROWCOUNT
ROWGUIDCOL
RULE
SAVE
SCHEMA
SECURITYAUDIT
SELECT
SEMANTICKEYPHRASETABLE
SEMANTICSIMILARITYDETAILSTABLE
SEMANTICSIMILARITYTABLE
SESSION_USER
SET
SETUSER
SHUTDOWN
SOME
STATISTICS
SYSTEM_USER
TABLE
TABLESAMPLE
TEXTSIZE
THEN
TO
TOP
TRAN
TRANSACTION
TRIGGER
TRUNCATE
TRY_CONVERT
TSEQUAL
UNION
UNIQUE
UNPIVOT
UPDATE
UPDATETEXT
USE
USER
VALUES
VAR_POP
VAR_SAMP
VARBINARY
VARCHAR
VARCHAR2
VARCHARACTER
VARIABLE
VARIABLES
VARYING
VERBOSE
VIEW
VOLATILE
WAITFOR
WHEN
WHENEVER
WHERE
WHILE
WIDTH_BUCKET
WINDOW
WITH
WITHIN
WITHOUT
WORK
WRITE
WITHIN GROUP
WRITETEXT
X509
XOR
YEAR
YEAR_MONTH
ZEROFILL
ZONE
```
[simon]: https://www.simonholywell.com/?utm_source=sqlstyle.guide&utm_medium=link&utm_campaign=md-document
"SimonHolywell.com"
[issue]: https://github.com/treffynnon/sqlstyle.guide/issues
"SQL style guide issues on GitHub"
[fork]: https://github.com/treffynnon/sqlstyle.guide/fork
"Fork SQL style guide on GitHub"
[pull]: https://github.com/treffynnon/sqlstyle.guide/pulls/
"SQL style guide pull requests on GitHub"
[issue]: https://github.com/SQLServerIO/sqlstyle.guide/issues
"SQL Server style guide issues on GitHub"
[fork]: https://github.com/SQLServerIO/sqlstyle.guide/fork
"Fork SQL Server style guide on GitHub"
[pull]: https://github.com/SQLServerIO/sqlstyle.guide/pulls/
"SQL Server style guide pull requests on GitHub"
[celko]: https://www.amazon.com/gp/product/0120887975/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=treffynnon-20&linkId=9c88eac8cd420e979675c815771313d5
"Joe Celko's SQL Programming Style (The Morgan Kaufmann Series in Data Management Systems)"
[dl-md]: https://raw.githubusercontent.com/treffynnon/sqlstyle.guide/gh-pages/_includes/sqlstyle.guide.md
[dl-md]: https://raw.githubusercontent.com/SQLServerIO/sqlstyle.guide/gh-pages/_includes/sqlstyle.guide.md
"Download the guide in Markdown format"
[iso-8601]: https://en.wikipedia.org/wiki/ISO_8601
"Wikipedia: ISO 8601"
[rivers]: http://practicaltypography.com/one-space-between-sentences.html
"Practical Typography: one space between sentences"
[reserved-keywords]: #reserved-keyword-reference
"Reserved keyword reference"
"Reserved keyword reference"
[sql-server-reserved-keywords] https://msdn.microsoft.com/en-us/library/ms189822.aspx
"Microsoft: SQL Server keyword reference"
[eav]: https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model
"Wikipedia: Entityattributevalue model"
[self]: http://www.sqlstyle.guide
"SQL style guide by Simon Holywell"
[self]: https://sqlserverio.github.com/sqlstyle.guide
"SQL Server style guide by Wes Brown"
[licence]: http://creativecommons.org/licenses/by-sa/4.0/
"Creative Commons Attribution-ShareAlike 4.0 International License"