***Why: consistent with the Microsoft's .NET Framework. Caps grap too much attention.***
***Why: consistent with the Microsoft's .NET Framework. Caps grab too much attention.***
#### 5. Use meaningful names for variables. The following example uses seattleCustomers for customers who are located in Seattle:
```csharp
varseattleCustomers=fromcustincustomers
wherecust.City=="Seattle"
selectcust.Name;
varseattleCustomers=fromcustomerincustomers
wherecustomer.City=="Seattle"
selectcustomer.Name;
```
***Why: consistent with the Microsoft's .NET Framework and easy to read.***
@@ -99,6 +99,7 @@ UriPart uriPart;
***Why: consistent with the Microsoft's .NET Framework and prevents inconsistent abbreviations.***
#### 7. Do use PascalCasing or camelCasing (Depending on the identifier type) for abbreviations 3 characters or more (2 chars are both uppercase when PascalCasing is appropriate or inside the identifier).:
#### 24. DO use two parameters named sender and e in event handlers. The sender parameter represents the object that raised the event. The sender parameter is typically of type object, even if it is possible to employ a more specific type.
```csharp
public void ReadBarcodeEventHandler(object sender, ReadBarcodeEventArgs e)
{
//...
}
```
***Why: consistent with the Microsoft's .NET Framework***
***Why: consistent with the Microsoft's .NET Framework and consistent with prior rule of no type indicators in identifiers.***
@@ -407,6 +415,17 @@ public class BarcodeReadException : System.Exception
***Why: consistent with the Microsoft's .NET Framework and easy to read.***
#### 26. Do use prefix Any, Is, Have or similar keywords for boolean identifier :
```csharp
// Correct
public static bool IsNullOrEmpty(string value) {
return (value == null || value.Length == 0);
}
```
***Why: consistent with the Microsoft's .NET Framework and easy to read.***
## Offical Reference
1. [MSDN General Naming Conventions](http://msdn.microsoft.com/en-us/library/ms229045(v=vs.110).aspx)
- [How to Write a Git Commit Message ](http://www.chrisbeams.com/posts/git-commit/)
- [How to Write a Git Commit Message ](https://webcache.googleusercontent.com/search?q=cache:PM7POmjONvgJ:https://chris.beams.io/posts/git-commit/+&cd=1&hl=sl&ct=clnk&gl=si&client=firefox-b-d)
[Naming convention][99] is a set of rules for choosing the character sequence to be used for identifiers which denote variables, types, functions, and other entities in source code and documentation.
Reasons for using a naming convention (as opposed to allowing programmers to choose any character sequence) include the following:
- To reduce the effort needed to read and understand source code;
- To enable code reviews to focus on more important issues than arguing over syntax and naming standards.
- To enable code quality review tools to focus their reporting mainly on significant issues other than syntax and style preferences.
[Naming convention](https://en.wikipedia.org/wiki/Naming_convention_(programming)) is a set of rules for choosing the character sequence to be used for identifiers which denote variables, types, functions, and other entities in source code and documentation.
Reasons for using a naming convention (as opposed to allowing programmers to choose any character sequence) include the following:
- To reduce the effort needed to read and understand source code.
- To enable code reviews to focus on more important issues than arguing over syntax and naming standards.
- To enable code quality review tools to focus their reporting mainly on significant issues other than syntax and style preferences.
## Table of Contents
- [SQL Server Object Name Convention](#sql-server-object-name-convention)
- [SQL Server Data Types Recommendation](#data-types-recommendation)
More details about SQL Server datatypes and mapping it with another databases you can find [here](https://github.com/ktaranov/sqlserver-kit/blob/master/SQL%20Server%20Data%20Types.md)
<a id="data-types-recommendation"></a>
More details about SQL Server data types and mapping it with another databases and program languages you can find [here](https://github.com/ktaranov/sqlserver-kit/blob/master/SQL%20Server%20Data%20Types.md)
| General Type | Type | Recommended | What use instead | Why use or not |
| Character Strings | [ntext][7] | No | **Deprecated** | [nvarchar(max)][6] | [NVARCHAR(MAX) VS NTEXT in SQL Server] |
| Character Strings | [text][7] | No | **Deprecated** | [varchar(max)][6] | [Differences Between Sql Server TEXT and VARCHAR(MAX) Data Type] |
| Binary Strings | [image][7] | No |**Deprecated** | [varbinary(max)][8]| [VARBINARY(MAX) Tames the BLOB] |
| Binary Strings | [binary][8] | Yes | **Deprecated** | [varbinary][8] | [Conversions between any data type and the binary data types are not guaranteed][8]|
[On the Advantages of DateTime2(n) over DateTime]:http://www.sqltact.com/2012/12/on-advantages-of-datetime2n-over.html
[Differences Between Sql Server TEXT and VARCHAR(MAX) Data Type]:https://sqlhints.com/2016/05/11/differences-between-sql-server-text-and-varcharmax-data-type/
[NVARCHAR(MAX) VS NTEXT in SQL Server]:https://www.sqlservercurry.com/2010/07/nvarcharmax-vs-ntext-in-sql-server.html
[VARBINARY(MAX) Tames the BLOB]:https://www.itprotoday.com/microsoft-visual-studio/varbinarymax-tames-blob
SQL Server TSQL Coding Conventions, Best Practices, and Programming Guidelines
<a id="t-sql-programming-style"></a>
SQL Server T-SQL Coding Conventions, Best Practices, and Programming Guidelines.
### General programming style
- Delimiters: spaces (not tabs)
- Avoid using asterisk in select statements `SELECT *`, use explicit column names. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-asterisk-select-list)
- No square brackets `[]` and [reserved words](https://github.com/ktaranov/sqlserver-kit/blob/master/Scripts/Check_Reserved_Words_For_Object_Names.sql) in object names and alias, use only Latin symbols **`[A-z]`** and numeric **`[0-9]`**
-Prefer [ANSI syntax](http://standards.iso.org/ittf/PubliclyAvailableStandards/c053681_ISO_IEC_9075-1_2011.zip) and functions
- All finished expressions should have `;` at the end (this is ANSI standard and Microsoft announced with the SQL Server 2008 release that semicolon statement terminators will become mandatory in a future version so statement terminators other than semicolons (whitespace) are currently deprecated. This deprecation announcement means that you should always use semicolon terminators in new development.)
More details [here](http://www.dbdelta.com/always-use-semicolon-statement-terminators/)
-All script files should end with `GO` and line break
- Avoid non-standard column aliases, use ,if required, double-quotes and always `AS` keyword: `SELECT p.LastName AS "Last Name" FROM dbo.Person AS p;`
### General programming T-SQL style
<a id="#general-t-sql-programming-style"></a>
-For database objects names in code use only schema plus object name, do not hardcode server and database names in your code: `dbo.MyTable` is good and bad `PRODSERVER.PRODDB.dbo.MyTable`.
More details [here](https://www.red-gate.com/simple-talk/opinion/editorials/why-you-shouldnt-hardcode-the-current-database-name-in-your-views-functions-and-stored-procedures/),
[here](https://www.sqlserverscience.com/basics/on-default-schemas-and-search-paths/) and [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-procedures-lack-schema-qualification).
-Delimiters: **spaces** (not tabs)
- Avoid using asterisk in select statements `SELECT *`, use explicit column names.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-asterisk-select-list).
- No square brackets `[]` and [reserved words](https://github.com/ktaranov/sqlserver-kit/blob/master/Scripts/Check_Reserved_Words_For_Object_Names.sql) in object names and alias, use only Latin symbols **`[A-z]`** and numeric **`[0-9]`**.
- All finished expressions should have semicolon `;` at the end.
This is ANSI standard and Microsoft announced with the SQL Server 2008 release that semicolon statement terminators will become mandatory in a future version so statement terminators other than semicolons (whitespace) are currently deprecated.
This deprecation announcement means that you should always use semicolon terminators in new development.
More details [here](http://www.dbdelta.com/always-use-semicolon-statement-terminators/).
- All script files should end with `GO` and line break.
- Keywords should be in **UPPERCASE**: `SELECT`, `FROM`, `GROUP BY` etc.
- Data types declaration should be in **lowercase**: `varchar(30)`, `int`, `real`, `nvarchar(max)` etc.
More details [here](https://www.sentryone.com/blog/aaronbertrand/backtobasics-lower-case-data-types).
- All system database and tables must be in **lowercase** for properly working for Case Sensitive instance: `master, sys.tables …`.
- Avoid non-standard column aliases, use, if required, double-quotes for special characters and always `AS` keyword before alias:
```sql
SELECT
p.LastName AS "Last Name"
FROM dbo.Person AS p;
```
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-avoid-non-standard-column-aliases).
All possible ways using aliases in SQL Server:
```sql
SELECT Tables = Schema_Name(schema_id)+'.'+[name] FROM sys.tables;
SELECT "Tables" = Schema_Name(schema_id)+'.'+[name] FROM sys.tables;
SELECT [Tables] = Schema_Name(schema_id)+'.'+[name] FROM sys.tables;
SELECT 'Tables' = Schema_Name(schema_id)+'.'+[name] FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] [Tables] FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] 'Tables' FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] "Tables" FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] Tables FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] AS [Tables] FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] AS 'Tables' FROM sys.tables;
SELECT Schema_Name(schema_id)+'.'+[name] AS Tables FROM sys.tables;
/* Below recommended due to ANSI
SELECT Schema_Name(schema_id)+'.'+[name] AS "Tables" FROM sys.tables;
```tsql
/* Recommended due to ANSI */
SELECT SCHEMA_NAME(schema_id) + '.' + "name" AS "Tables" FROM sys.tables;
/* Not recommended but possible */
SELECT SCHEMA_NAME(schema_id) + '.' + [name] AS "Tables" FROM sys.tables;
SELECT Tables = SCHEMA_NAME(schema_id) + '.' + [name] FROM sys.tables;
SELECT "Tables" = SCHEMA_NAME(schema_id) + '.' + [name] FROM sys.tables;
SELECT [Tables] = SCHEMA_NAME(schema_id) + '.' + [name] FROM sys.tables;
SELECT 'Tables' = SCHEMA_NAME(schema_id) + '.' + [name] FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] [Tables] FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] 'Tables' FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] "Tables" FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] Tables FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] AS [Tables] FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] AS 'Tables' FROM sys.tables;
SELECT SCHEMA_NAME(schema_id) + '.' + [name] AS Tables FROM sys.tables;
```
- The first argument in `SELECT` expression should be on the same line with it: `SELECT LastName …`
- Arguments are divided by line breaks, commas should be placed before an argument:
- The first argument in `SELECT` expression should be on the next line:
```sql
SELECT FirstName
SELECT
FirstName
```
- Arguments are divided by line breaks, commas should be placed before an argument:
```sql
SELECT
FirstName
, LastName
```
- For SQL Server >= 2012 use `FETCH-OFFSET` instead `TOP`. But if you use `TOP` avoid use `TOP` in a `SELECT` statement without an `ORDER BY`. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-top-without-order-select-statement)
- Use `TOP` function with brackets because `TOP` has supports use of an expression, such as `(@Rows*2)`, or a subquery: `SELECT TOP(100) LastName …`.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-avoiding-old-style-top-clause). Also `TOP` without brackets does not work with `UPDATE` and `DELETE` statements.
- For demo queries use `TOP(100)` or lower value because SQL Server SQL Server uses one sorting method for TOP 1-100 rows, and a different one for 101+ rows
More details [here](https://www.brentozar.com/archive/2017/09/much-can-one-row-change-query-plan-part-2/)
- Keywords and data types declaration should be in **UPPERCASE**
- `FROM, WHERE, INTO, JOIN, GROUP BY, ORDER BY` expressions should be aligned so, that all their arguments are placed under each other (see Example below)
- All objects must used with schema names but without database and server name: `FROM dbo.Table`. For stored procedure more details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-procedures-lack-schema-qualification)
- All system database and tables must be in lower case for properly working in Case Sensitive instance: `master, sys.tables …`
- For SQL Server >= 2012 use [`FETCH-OFFSET`] instead [`TOP`].
More details [here](https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows-returned).
But if you use [`TOP`] avoid use [`TOP`] in a `SELECT` statement without an `ORDER BY`.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-top-without-order-select-statement).
- If you using [`TOP`] (instead recommended [`FETCH-OFFSET`]) function with round brackets because [`TOP`] has supports use of an expression, such as `(@Rows*2)`, or a sub query: `SELECT TOP(100) LastName …`.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-avoiding-old-style-top-clause).
Also [`TOP`] without brackets does not work with `UPDATE` and `DELETE` statements.
```tsql
/* Not working without brackets () */
DECLARE @n int = 1;
SELECT TOP@n name FROM sys.objects;
```
- For demo queries use `TOP(100)` or lower value because SQL Server uses one sorting method for `TOP` 1-100 rows, and a different one for 101+ rows.
More details [here](https://www.brentozar.com/archive/2017/09/much-can-one-row-change-query-plan-part-2/).
- Avoid specifying integers in the `ORDER BY` clause as positional representations of the columns in the select list.
The statement with integers is not as easily understood by others compared with specifying the actual column name.
In addition, changes to the select list, such as changing the column order or adding new columns, requires modifying the `ORDER BY` clause in order to avoid unexpected results.
More details [here](https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#best-practices).
```sql
/* bad */
SELECT ProductID, Name FROM Production.Production ORDER BY 2;
/* good */
SELECT ProductID, Name FROM Production.Production ORDER BY Name;
```
- Avoid using [`ISNUMERIC`](https://docs.microsoft.com/en-us/sql/t-sql/functions/isnumeric-transact-sql) function. Use for SQL Server >= 2012 [`TRY_CONVERT`](https://docs.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql) function and for SQL Server < 2012 `LIKE` expression:
```sql
CASE WHEN Stuff(LTrim(TapAngle),1,1,'') NOT LIKE '%[^-+.ED0123456789]%' --is it a float?
AND Left(LTrim(TapAngle),1) LIKE '[-.+0123456789]'
AND TapAngle LIKE '%[0123456789][ED][-+0123456789]%'
AND Right(TapAngle ,1) LIKE N'[0123456789]'
THEN 'float'
WHEN Stuff(LTrim(TapAngle),1,1,'') NOT LIKE '%[^.0123456789]%' --is it numeric
AND Left(LTrim(TapAngle),1) LIKE '[-.+0123456789]'
AND TapAngle LIKE '%.%' AND TapAngle NOT LIKE '%.%.%'
AND TapAngle LIKE '%[0123456789]%'
THEN 'float'
```tsql
CASE WHEN STUFF(LTRIM(TapAngle),1,1,'') NOT LIKE '%[^-+.ED0123456789]%' /* is it a float? */
AND LEFT(LTRIM(TapAngle),1) LIKE '[-.+0123456789]'
AND TapAngle LIKE '%[0123456789][ED][-+0123456789]%'
AND RIGHT(TapAngle ,1) LIKE N'[0123456789]'
THEN 'float'
WHEN STUFF(LTRIM(TapAngle),1,1,'') NOT LIKE '%[^.0123456789]%' /* is it numeric? */
AND LEFT(LTRIM(TapAngle),1) LIKE '[-.+0123456789]'
AND TapAngle LIKE '%.%' AND TapAngle NOT LIKE '%.%.%'
AND TapAngle LIKE '%[0123456789]%'
THEN 'float'
ELSE NULL
END
```
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-avoid-using-isnumeric-function-e1029)
- Avoid using `INSERT INTO` a permanent table with `ORDER BY`, more details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-insert-permanent-table-order-pe020)
- Avoid using shorthand (`wk, yyyy, d` etc.) with date/time operations, use full names: `month, day, year`. More details [here](https://sqlblog.org/2011/09/20/bad-habits-to-kick-using-shorthand-with-date-time-operations)
- Avoid ambiguous formats for date-only literals, use `CAST('yyyymmdd' AS DATE)` format
- Avoid treating dates like strings and avoid calculations on the left-hand side of the `WHERE` clause. More details [here](https://sqlblog.org/2009/10/16/bad-habits-to-kick-mis-handling-date-range-queries)
- Avoid using [hints](https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql) except `OPTION(RECOMPILE)` if needed. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-a-hint-is-used-pe004-7)
- Avoid use of `SELECT…INTO` for production code, use instead `CREATE TABLE` + `INSERT INTO …` approach. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/use-selectinto-statement)
- Use only ISO standard JOINS syntaxes. The “old style” Microsoft/Sybase JOIN style for SQL, which uses the `=*` and `*= syntax, has been deprecated and is no longer used. Queries that use this syntax will fail when the database engine level is 10 (SQL Server 2008) or later (compatibility level 100). The ANSI-89 table citation list (FROM tableA, tableB) is still ISO standard for INNER JOINs only. Neither of these styles are worth using. It is always better to specify the type of join you require, INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER and CROSS, which has been standard since ANSI SQL-92 was published. While you can choose any supported JOIN style, without affecting the query plan used by SQL Server, using the ANSI-standard syntax will make your code easier to understand, more consistent, and portable to other relational database systems.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-old-style-join-syntax-st001)
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-avoid-using-isnumeric-function-e1029).
- Avoid using `INSERT INTO` a permanent table with `ORDER BY`.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-insert-permanent-table-order-pe020).
- Avoid using shorthand (`wk, yyyy, d` etc.) with date/time operations, use full names: `month, day, year`.
More details [here](https://sqlblog.org/2011/09/20/bad-habits-to-kick-using-shorthand-with-date-time-operations).
- Avoid ambiguous formats for date-only literals, use `CAST('yyyymmdd' AS DATE)` format.
- Avoid treating dates like strings and avoid calculations on the left-hand side of the `WHERE` clause.
More details [here](https://sqlblog.org/2009/10/16/bad-habits-to-kick-mis-handling-date-range-queries).
- Avoid using [hints](https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql) except `RECOMPILE` if needed and `NOEXPAND` (see next tip).
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/sql-prompt-code-analysis-a-hint-is-used-pe004-7).
- Use [`NOEXPAND`](https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table#using-noexpand) hint for [indexed views](https://docs.microsoft.com/sql/relational-databases/views/create-indexed-views) on non enterprise editions and Prior to SQL Server 2016 (13.x) SP1 to let the query optimizer know that we have indexes.
More details [here](https://bornsql.ca/blog/using-indexed-views-dont-forget-this-important-tip/).
- Avoid use of `SELECT…INTO` for production code, use instead `CREATE TABLE` + `INSERT INTO …` approach. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/use-selectinto-statement).
- Use only ISO standard JOINS syntaxes. The *old style* Microsoft/Sybase `JOIN` style for SQL, which uses the `=*` and `*=` syntax, has been deprecated and is no longer used.
Queries that use this syntax will fail when the database engine level is 10 (SQL Server 2008) or later (compatibility level 100). The ANSI-89 table citation list (`FROM tableA, tableB`) is still ISO standard for `INNER JOINs` only. Neither of these styles are worth using.
It is always better to specify the type of join you require` INNER`, `LEFT OUTER`, `RIGHT OUTER`, `FULL OUTER` and `CROSS`, which has been standard since ANSI SQL-92 was published. While you can choose any supported `JOIN `style, without affecting the query plan used by SQL Server, using the ANSI-standard syntax will make your code easier to understand, more consistent, and portable to other relational database systems.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-old-style-join-syntax-st001).
- Do not use a scalar user-defined function (UDF) in a `JOIN` condition, `WHERE` search condition, or in a `SELECT` list, unless the function is [schema-bound](https://docs.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql#best-practices).
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/misuse-scalar-user-defined-function-constant-pe017)
- Use `EXISTS` or `NOT EXISTS` if referencing a subquery, and `IN` or `NOT IN` when have a list of literal values
More details [here](https://www.brentozar.com/archive/2018/08/a-common-query-error/)
- For concatenate strings:
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/misuse-scalar-user-defined-function-constant-pe017).
- Use `EXISTS` or `NOT EXISTS` if referencing a subquery, and `IN` or `NOT IN` when have a list of literal values.
More details [here](https://www.brentozar.com/archive/2018/08/a-common-query-error/).
- For concatenate unicode strings:
- always using the upper-case `N`;
- always store into a variable of type `NVARCHAR(MAX)`;
- avoid truncation of string literals, simply ensure that one piece is converted to `NVARCHAR(MAX)`.
More details [here](https://themondaymorningdba.wordpress.com/2018/09/13/them-concatenatin-blues/)
- Always specify a length to any text-based data type such as `NVARCHAR` or `VARCHAR`: `DECLARE @myGoodVariable VARCHAR(50);` and not `DECLARE @myBadVariable VARCHAR;`.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/using-a-variable-length-datatype-without-explicit-length-the-whys-and-wherefores)
- always store into a variable of type `nvarchar(max)`;
- avoid truncation of string literals, simply ensure that one piece is converted to `nvarchar(max)`.
Example:
```tsql
DECLARE @nvcmaxVariable nvarchar(max);
SET @nvcmaxVariable = CAST(N'ಠ russian anomaly ЯЁЪ ಠ ' AS nvarchar(max)) + N'something else' + N'another';
SELECT @nvcmaxVariable;
```
More details [here](https://themondaymorningdba.wordpress.com/2018/09/13/them-concatenatin-blues/).
- Always specify a length to any text-based data type such as `varchar`, `nvarchar`, `char`, `nchar`:
```tsql
/* bad */
DECLARE @myBadVarcharVariable varchar;
DECLARE @myBadNVarcharVariable nvarchar;
DECLARE @myBadCharVariable char;
DECLARE @myBadNCharVariable nchar;
/* good */
DECLARE @myGoodVarchareVariable varchar(50);
DECLARE @myGoodNVarchareVariable nvarchar(90);
DECLARE @myGoodCharVariable char(7);
DECLARE @myGoodNCharVariable nchar(10);
```
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/using-a-variable-length-datatype-without-explicit-length-the-whys-and-wherefores).
- Use only [`ORIGINAL_LOGIN()`](https://docs.microsoft.com/en-us/sql/t-sql/functions/original-login-transact-sql) function because is the only function that consistently returns the actual login name that we started with regardless of impersonation.
More details [here](https://sqlstudies.com/2015/06/24/which-user-function-do-i-use/).
- Always use `IF` statement with `BEGIN-END` block to prevent errors with multi line statements:
```tsql
DECLARE @x int = 0;
DECLARE @y int = 1;
/* bad */
IF @y > @x
SET @x = @x + 1;
SET @y = @y - 1;
ELSE
PRINT(1);
/* Msg 156, Level 15, State 1, Line 8
Incorrect syntax near the keyword 'ELSE'. */
/* good */
IF @y > @x
BEGIN
SET @x = @x + 1;
SET @y = @y - 1;
END;
ELSE
BEGIN
PRINT(1);
END;
```
- `FROM, WHERE, INTO, JOIN, GROUP BY, ORDER BY` expressions should be aligned so, that all their arguments are placed under each other (see Example below)
Example:
TSQL Example with formating:
```sql
```tsql
WITH CTE_MyCTE AS (
SELECTt1.Value1ASVal1
,t1.Value2ASVal2
,t2.Value3ASVal3
SELECT
t1.Value1 AS Val1
, t1.Value2 AS Val2
, t2.Value3 AS Val3
INNER JOIN dbo.Table3 AS t2
ON t1.Value1 = t2.Value1
WHEREt1.Value1>1
ANDt2.Value2>=101
WHERE t1.Value1 > 1
AND t2.Value2 >= 101
)
SELECTt1.Value1ASVal1
,t1.Value2ASVal2
,t2.Value3ASVal3
INTO#Table3
FROMCTE_MyCTEASt1
ORDERBYt2.Value2;
SELECT
t1.Value1 AS Val1
, t1.Value2 AS Val2
, t2.Value3 AS Val3
INTO #Table3
FROM CTE_MyCTE AS t1
ORDER BY t2.Value2;
```
**[⬆ back to top](#table-of-contents)**
<a id="programming-style"></a>
### Stored procedures and functions programming style
- All stored procedures and functions should use `ALTER` statement and start with the object presence check
### Stored procedures and functions programming style
<a id="programming-style"></a>
- All stored procedures and functions should use `ALTER` statement and start with the object presence check (see example below)
- `ALTER` statement should be preceded by 2 line breaks
- Parameters name should be in **camelCase**
- Parameters should be placed under procedure name divided by line breaks
- After the `ALTER` statement and before AS keyword should be placed a comment with execution example
- The procedure or function should begin with parameters check
- After the `ALTER` statement and before `AS` keyword should be placed a comment with execution example
- The procedure or function should begin with parameters checks (see example below)
- Create `sp_` procedures only in `master` database - SQL Server will always scan through the system catalog first
- Always use `BEGIN TRY` and `BEGIN CATCH`
- Always use `/* */` instead in-line comment `--`
- Use `SET NOCOUNT ON;` for stops the message that shows the count of the number of rows affected by a Transact-SQL statement. More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-set-nocount-problem-pe008-pe009)
- Do not use `SET NOCOUNT OFF;` (because it is default behavior)
- Use `RAISERROR` instead `PRINT` if you want to give feedback about the state of the currently executing SQL batch without lags. More details [here](http://sqlity.net/en/984/print-vs-raiserror/) and [here](http://sqlservercode.blogspot.com/2019/01/print-disruptor-of-batch-deletes-in-sql.html)
- Use `TOP` expression with `()`:
```tsql
-- Not working without ()
DECLARE@nint=1;
SELECTTOP@nnameFROMsys.objects;
```
- Always use `BEGIN TRY` and `BEGIN CATCH` for error handling
- Use `SET NOCOUNT ON;` for stops the message that shows the count of the number of rows affected by a Transact-SQL statement and decreasing network traffic.
More details [here](https://www.red-gate.com/hub/product-learning/sql-prompt/finding-code-smells-using-sql-prompt-set-nocount-problem-pe008-pe009).
- Do not use `SET NOCOUNT OFF;` because it is default behavior
- Use `RAISERROR` instead `PRINT` if you want to give feedback about the state of the currently executing SQL batch without lags.
More details [here](http://sqlity.net/en/984/print-vs-raiserror/) and [here](http://sqlservercode.blogspot.com/2019/01/print-disruptor-of-batch-deletes-in-sql.html).
- All code should be self documenting
- TSQL code, triggers, stored procedures, functions, should have a standard comment banner:
', User name: ' + CAST(ORIGINAL_LOGIN(), sysname);
PRINT ERROR_MESSAGE();
END CATCH;
GO
```
@@ -318,27 +482,133 @@ GO
**[⬆ back to top](#table-of-contents)**
<a id="reference"></a>
### Dynamic T-SQL Recommendation
<a id="dynamic-t-sql-recommendation"></a>
**Highly recommended to read awesome detailed article about dynamic T-SQL by Erland Sommarskog: [The Curse and Blessings of Dynamic SQL](http://sommarskog.se/dynamic_sql.html)**
Dynamic SQL is a programming technique that allows you to construct SQL statements dynamically at runtime.
It allows you to create more general purpose and flexible SQL statement because the full text of the SQL statements may be unknown at compilation.
For example, you can use the dynamic SQL to create a stored procedure that queries data against a table whose name is not known until runtime.
More details [here](http://www.sqlservertutorial.net/sql-server-stored-procedures/sql-server-dynamic-sql/).
- Do not use [nvarchar(max)][6] for your object’s name parameter, use [sysname](https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms191240(v=sql.105)?redirectedfrom=MSDN) instead (synonym for nvarchar(128) except that, by default, sysname is NOT NULL).
DECLARE @tableName sysname = N'My badly named table!';
SET @tsql = N'SELECT object_id FROM ' + @tableName;
/* Good */
DECLARE @tsql nvarchar(max);
DECLARE @tableName sysname = N'My badly named table 111!';
SET @tsql = N'SELECT object_id FROM ' + QUOTENAME(@tableName);
```
- Always use [`sp_executesql`] instead [`EXEC`] to prevent sql injection.
Also [`sp_executesql`] can parameterizing your dynamic statement that means plans can be reused as well (when the value of the dynamic object is the same).
Also [`sp_executesql`] can even be used to output values as well (see example below).
```tsql
/* Bad EXEC example with sql injection*/
DECLARE @tsql nvarchar(max);
DECLARE @tableName sysname = N'master.sys.tables; SELECT * FROM master.sys.server_principals;';
SET @tsql = N'SELECT "name" FROM ' + @tableName + N';';
- [SQL Server Code Review Checklist for Developers](https://www.sqlshack.com/sql-server-code-review-checklist-for-developers/) (by Samir Behara)
@@ -346,5 +616,14 @@ GO
- [In The Cloud: The Importance of Being Organized](http://sqlblog.com/blogs/john_paul_cook/archive/2017/05/16/in-the-cloud-the-importance-of-being-organized.aspx)
- [Naming Conventions in Azure](http://www.sqlchick.com/entries/2017/6/24/naming-conventions-in-azure)
- [The Basics of Good T-SQL Coding Style – Part 3: Querying and Manipulating Data](https://www.simple-talk.com/sql/t-sql-programming/basics-good-t-sql-coding-style-part-3-querying-manipulating-data/)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.