[Link].
pe
Good Practices - Database - SQL Server
Transact-SQL Standards
Good Practices of
Programming
Page 1 of 12
[Link]
Good Practices - Database - SQL Server
1. Naming Conventions and Standards
Note: The terms 'Pascal notation' and 'Camel notation' are
used through this document.
Pascal Notation - The first character of all words is
WRITE IN UPPERCASE AND THE OTHER CHARACTERS IN LOWERCASE.
BackgroundColor
Camel Notation - The first character of all words,
Except for the first word, it is written in uppercase and the others.
lowercase characters.
Example: backgroundColor
Use Pascal notation for the name of the tables
CREATE TABLE [Link]
2. Use Pascal notation for the table field names
CREATE TABLE [Link]
(
EmployeeId INT,
FirstName VARCHAR(20)
LastName VARCHAR(20)
)
3. Never use "sp_", the reason is that: SQL Server recognizes the
prefix "sp_" as "System Stored Procedure", that is, a
stored procedure of System and I would search for it in the Database
Data.
Usa la siguiente sintaxis para los nombres de los Stored
procedures:
Usp_<Schema Name>_<Table Name>_<Action>
Example:
usp_GEN_Employee_Insert
usp_GEN_Employee_GetAll
4. Use diagrams to group objects like tables, the names
They must be abbreviated.
Incorrect:
GEN_Employee
Correct
Page 2 of 12
[Link]
Good Practices - Database - SQL Server
[Link]
Page 3 of 12
[Link]
Good Practices - Database - SQL Server
2. Considerations in database design
The name of the database must resemble the name of the
application, should not contain the prefix DB, as it would be
redundantly indicating that it is a database.
Use Pascal notation for the name.
Incorrect
Sales_DB
Correct:
Sales
2. Record deletion. It is recommended NOT to physically delete.
a record of firsts. Change it to a 'low' state.
3. Create audit fields that store the last values
executed by the user:
FechaRegistro
Responsible
Machine
IP
4. Avoid creating fields that accept NULLs, only apply it for the
fields that really require it.
5. Implement 'SET NOCOUNT ON' in your queries.
Page 4 of 12
[Link]
Good Practices – Database – SQL Server
When executing DML statements in a stored procedure,
the SQL server returns a message indicating the number of rows
affected by the process. Although this information may be useful
to debug the code, it becomes obsolete if it is not being debugged. To
establish the use of SET NOCOUNT ON, the function is disabled.
in return for this additional information. In procedures
almacenados formados por varias instrucciones o declaraciones de
DML statements, enabling SET NOCOUNT ON can help us
achieve a considerable increase in performance, furthermore, if
we take into account a database that contains dozens of
Stored Procedures for use in an oriented application
to multiple clients at the same time, a detail as simple as
this could make a notable difference. It could be used as a way
for example the following skeleton:
CREATE PROC [Link]
(
@variable_1 INT
@variable_2 VARCHAR(10)
@variable_n BIT
)
AS
BEGIN
SET NOCOUNT ON;
--INSTRUCTION 1
--INSTRUCTION 2
INSTRUCTION N
SET NOCOUNT OFF
END
6. Avoid using 'SELECT *'
Although it may be easy and convenient to use the wildcard (*) to bring everything
the fields, this must be omitted and instead specified the
fields that need to be brought. The use of the wildcard prevents
also an effective efficient use of indexes. In case
that they all be as the use of the '*' establishes, specify each
one of them, a simple ALT+F1 over the name of the table
selected will bring its structure, so copy, paste the
fields and adding a comma requires minimal effort.
I have encountered several times that when doing a check of
Existence is usually referred to with the following syntax:
IF EXISTS (SELECT * FROM Table WHERE Field =
Conditioning
BEGIN
--INSTRUCTIONS 1,2…N
END
Avoid it, there is no reason to load more work onto the database.
of data bringing all fields if the only thing that is desired to know
Yes, it exists. The * can easily be replaced with '' or 1.
fulfilling its function of checking existence without need
to bring data:
IF EXISTS (SELECT '' FROM Table WHEREField =
Conditioning
BEGIN
Page 5 of 12
[Link]
Good Practices - Database - SQL Server
--INSTRUCTIONS 1,2…N
END
Or well:
IF EXISTS (SELECT 1 FROM Table WHERE Field =
Conditioning
BEGIN
--INSTRUCTIONS 1,2…N
END
Both will provide the same functionality without the need to load.
additional and unnecessary work to the database.
[Link] NOLOCK... wisely.
El uso deNOLOCKpuede mejorar considerablemente la velocidad
from some queries. When using NOLOCK in the queries it
establishes that the reading does not "trap" the table and it can be read
at the same time by all users. However, it is necessary to
take into account that the dataset shown is
considered as a 'dirty read'. This means that the data
shown may not be entirely accurate, as these could
to find oneself in the middle of some transaction
type DELETE, UPDATE or INSERT. Still, for the case of tables
static as in some cases those dedicated to fixed catalogs and
for reporting scenarios where the information is mostly
historical and therefore will not be affected at the moment,
It could represent an acceptable improvement, especially if they are inquiries.
frequent in a multi-user environment.
NOLOCK cannot be used indiscriminately in all
Stored Procedures is more of an evaluation issue.
about specific scenarios.
NOLOCK is used when performing a query and only applies
to the tables. Its structure would be the following:
SET NOCOUNT ON
SELECT
Field1,
Field2
.
.
CampoN
FROM Table1T1(NOLOCK)
INNER JOIN Table2 T2(NOLOCK) ON [Link]=[Link]
INNER JOIN Table3 T3(NOLOCK) ON [Link] = [Link]
WHERE
<Condicionantes>
SET NOCOUNT OFF
8. Use SP_EXECUTESQL instead of EXECUTE.
The use of sp_executesql is recommended, instead of the
instruction EXECUTE or EXEC when executing dynamic code. This
because sp_executesql allows for substitution of
parameters, it is much more versatile than EXECUTE and furthermore
generates execution plans; which increases the chances of
that when used again it becomes more effective.
Page 6 of 12
[Link]
Best Practices - Database - SQL Server
9. Avoid the use of CURSORS
Cursors are a tool used to access and modify
el resultado de una cláusulaSELECTfila por fila. El problema con
its use is that they consume an enormous amount of resources,
especially by memory. Whenever possible, it should be
omit the use of cursors or minimize their implementation. Some
alternatives and substitutes to the use of cursors can be:
. Use WHILE loops.
. Use of derived tables.
. Use of correlated subqueries.
. Use of CASE.
. Use of multiple queries.
. The combination of all the above.
10. Use the variables TABLE TYPE & TABLES appropriately
TEMPORARY
Is it always better to use table-type variables instead of tables?
temporales?, let's review the characteristics and differences between one and
another.
Table type variables:
. Its use in stored procedures causes less re
compilations.
. They target memory structures, which produces less.
resource consumption than temporary tables.
. Its content is not always in memory. In case it is
insert a large number of records this is stored
inTEMPDB.
. The content of the variable is not affected by the
ROLLBACK command.
. They cannot be generated on the fly.
. They do not use parallelism (multiple threads) in their execution plan.
Its use for high concurrency tables or with a large amount
data can affect your performance, being lower in
comparison with a temporary table.
. Indexes cannot be added to them.
. They cannot be modified or truncated once created.
Temporary tables:
. They are automatically stored in the TEMPDB database.
. Its creation can cause blockages in the
tablassysobjects,sysindexes affect the entire server.
. Allows the use of indexes.
. Its use in stored procedures can cause a re
continuous integration.
. Roughly speaking, they can be treated like a normal table.
In general, it is recommended to always use table-type variables.
Page 7 of 12
[Link]
Good Practices - Database - SQL Server
that it is possible instead of temporary tables. Use the latter
only in case a very large amount is handled
information and always trying to create its structure beforehand
never creating them 'on the fly'.
11. Implementation of dynamic SQL (or red code).
Although the use of dynamic SQL is generally somewhat condemned
due to a poor implementation can result in a crack
of security that leads to a severe case of SQL Injection.
The suggested implementation is encapsulated within a
stored procedure, it is not entirely dynamic for the
client application, that is, it does not allow you to structure sentences.
free and is mainly oriented towards procedures
stored procedures whose main function is a parameterized query
with options variables. To use the base of data
AdventureWorksDW2008R2 to illustrate an example. We will test.
with the following stored procedure:
CREATE PROCEDURE BeforeRedCodeSELECT
(
@ProductKey INT=NULL,
@SalesOrderLineNumber TINYINT=NULL,
@OrderQuantity SMALLINT=NULL,
@CurrencyKey INT=NULL
)
AS
BEGIN
SET NOCOUNT ON
SELECT
[Link]
[Link]
[Link],
[Link]
[Link],
[Link]
FROM FactInternetSales FIS(NOLOCK)
WHERE [Link]=ISNULL(@ProductKey, [Link])
AND [Link] = ISNULL(@SalesOrderLineNumbe
r, [Link]
AND [Link]= ISNULL (@OrderQuantity, [Link]
antity
AND [Link]= ISNULL (@CurrencyKey, [Link]
)
SET NOCOUNT OFF
END
In this case, the query accepts null values and uses ISNULL(se
you can use COALESCE instead, but for practical reasons in
the example doesn't make much sense and ISNULL is a bit faster
to give flexibility to the procedure
stored and able to consult using either one, four or
any combination of parameters. Now, converting the
The dynamic SQL query would look as follows:
CREATE PROCEDURE AfterRedCodeSELECT
Page 8 of 12
[Link]
Good Practices – Database – SQL Server
(
@ProductKey INT=NULL
@SalesOrderLineNumber TINYINT=NULL,
Order Quantity SMALLINT=NULL,
@CurrencyKey INT=NULL
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @Query AS NVARCHAR(MAX)
SET @Query=N'
SELECT
[Link]
[Link]
[Link],
[Link],
[Link],
[Link]
FROM FactInternetSales FIS(NOLOCK)
WHERE 1=1 '
IF @ProductKey IS NOT NULL
BEGIN
SET @Query = @Query + AND [Link] = @ProductKey
END
IF @SalesOrderLineNumber IS NOT NULL
BEGIN
SET @Query = @Query + AND [Link] =
@SalesOrderLineNumber '
END
IF @OrderQuantity IS NOT NULL
BEGIN
SET @Query = @Query + AND [Link] = @OrderQuantity
'
END
IF @CurrencyKey IS NOT NULL
BEGIN
SET @Query = @Query + AND [Link] =@CurrencyKey
END
--PRINT @Query
EXECUTE sp_executesql@Query
, N'@ProductKey INT, @SalesOrderLineNumber TINYINT,
@OrderQuantity SMALLINT, @CurrencyKey INT
, @ProductKey = @ProductKey
, @SalesOrderLineNumber = @SalesOrderLineNumber
, Order Quantity = @OrderQuantity
, @CurrencyKey = @CurrencyKey
SET NOCOUNT OFF
END
Here the stored procedure will only include the conditions that
they are necessary and do not have a null value. Both
procedures return the same results and are equivalent
one another. Using SQL Profiler, we can appreciate the difference
in resource optimization:
Page 9 of 12
[Link]
Good Practices - Database - SQL Server
Readings are reduced for this particular scenario, by little.
more than 80%, the duration at 60% and in CPU usage, a
total change.
From what can be seen, Dynamic SQL may not be that bad.
as it seems and can offer us creative alternatives for
optimize our queries. I evaluated their complex queries and
heavy to weigh if a refactoring using Dynamic SQL
can help you, always ensuring that it does not lend itself to
SQL Injection cases.
12. Apply INDEXES in an optimized way.
It is already well known the use of indexes to speed up queries.
in SQL Servers and other database engines. These indicate
to the current database engine, that column or set
Columns will be used more frequently, which makes that
the data is stored in memory for access
more efficient to the data.
It is advisable for the indexes to be formed on the fields that
find frequently in some of the following
scenarios:
. SonPRIMARY KEYoFOREIGN KEY.
. They are frequently used to link tables with JOIN.
. They are commonly used within procedures
stored or in queries paired with any of the
following commands: BETWEEN, ORDER BY, GROUP BY, TOP
DISTINCT(Although we already mentioned that these must be
avoid it as much as possible; if there is no other alternative, it must be done.
consider their fields for the application of indices.
. They are commonly used for filters in the WHERE clause.
Although the indices generate an improvement in times of
response, it is also not possible to abuse them indiscriminately.
In contrast to its improvement in response time, each index
it takes up space equivalent to the number of records in the table,
Page 10 of 12
[Link]
Good Practices - Database - SQL Server
penalizing performance in the database by
execute INSERT, UPDATE, and DELETE.
Avoid creating indexes on fields that contain few values.
like those that are of type BIToCHAR (from one to four) and
make sure not to add the same index with different names.
The in-depth study of creation, design, and maintenance of
indexes escape the scope of this article (I hope to write something
more elaborate on the topic of indices in the future), however
It is important to take the time to understand them. Their
correct application can greatly favor the time of
response to your inquiries.
[Link] recommendations:
. If the stored procedure contains too many
IF-ELSE statements to execute different processes according to
certain parameters, it is more efficient to separate each block and
encapsulate them in different stored procedures; This
to prevent the execution plan from changing according to the value of
result of the IF expression, wasting the advantage of this
the execution plan in memory and pre-compilation.
. Avoid using the SELECT-INTO statement. When executed, it
they block the tables involved. Instead, apply the
INSERT INTO - SELECT statement.
. Always try to use the JOIN instruction before any sub
consultation.
. Use the BETWEEN instruction instead of IN whenever possible.
possible.
. In the case that the LIKE instruction is used, avoid the use of the
wildcard "%" at the beginning of the string to search. This is because if
it applies, the search would have to read all the data from the table or
tables involved to answer the query. It is recommended
that there are at least three characters before the wildcard.
. Avoid the use of DISTINCT as much as possible
. In case of using the UNION instruction and there was security of
that no records will be obtained in the involved SELECTs
duplicates, so the recommended thing in this scenario is
replace UNION with UNION ALL to prevent its use
implicit from the DISTINCT instruction, since this increases the
resource consumption.
. Avoid using ORDER BY whenever possible. Just like
DISTINCT consumes a high amount of resources.
Consider if it is really necessary to use it or, if on the other hand, it
you can leave the sorting of the results to the application that
you will receive the data.
. Use SQL Profiler to trace for performance analysis.
of the most concurrent stored procedures and see
options to refactor the process. Pay special attention to
the columns CPU, Duration, readsywrites to optimize the
memory usage and the generated I/O.
. Keep transactions as short as possible within a
stored procedure. This favors the reduction of
number of blocks, promoting to accelerate performance
database general.
Page 11 of 12
[Link]
Good Practices - Database - SQL Server
. Use the Execution Plan to review your queries, understand
how SQL Server is executing its queries and evaluated your
suggestions.
. If you need to store very large volumes of text, but they are
less than 8000 characters, use the VARCHAR data type instead
deTEXT.
. I carefully evaluated the use of CHAR and VARCHAR depending
if the field in which it will be used varies a lot in size or not.
This is to weigh speed performance against performance of
storage. SQL Server processes columns faster of
fixed length. Use CHAR for columns with little variation in
length and VARCHAR for those that do not have a length
stable or average.
. Do not use columns with data types FLOAT, REAL or
DATETIME as FOREIGN KEY.
Página 12 de 12