Для загрузки Стандарты и правила доступны по следующий ссылке на моем сайте: http://www.msmirnov.ru/public/TSQL_Coding_Standards.doc
Либо с ними можно ознакомиться прямо здесь.
Стандарт оформления кода T-SQL
Цель документа
Документ является соглашением по оформлению и написанию кода на языке T-SQL. В документе приведены основные правила оформления кода и приемы, используемые при написании программ.
Цели документа:
- предоставить общие правила, позволяющие сохранить единый стиль написания кода, облегчив тем самым его понимание всеми участниками команды;
- ввести базовые правила написания программ, что позволит повысить предсказуемость выполнения программ, а также избежать ошибок при написании программ новыми участниками команды, не знакомыми с внутренними стандартами разработки.
Стили именования
- Pascal case – первая буква каждого слова в имени идентификатора начинается с верхнего регистра.
Пример: TheCategory;
- Camel case – первая буква первого слова в идентификаторе в нижнем регистре, все первые буквы последующих слов – в верхнем.
Пример: theCategory;
- UpperCase – стиль используется только для сокращений, все буквы в имени идентификатора в верхнем регистре.
Пример: ID;
- Hungarian notation – перед именем идентификатора пишется его тип в сокращенной форме.
Пример: strFirstName, iCurrentYear.
Правила именования объектов базы данных
- Имена баз данных должны быть оформлены в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному назначению баз данных.
- Имена таблиц должны быть оформлено в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному назначению таблиц. Не допускается использование пробелов или специальных символов в имени таблиц баз данных, а также символов национального алфавита.
- Имена полей таблиц должно быть оформлено в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному назначению полей. Не допускается использование пробелов или специальных символов в имени поля таблицы, а также символов национального алфавита.
Первичные ключи в таблицах должны именоваться как ID.
В сложных случаях, когда есть базовая таблица и несколько зависимых, имя зависимой таблицы формируется из имени базовой таблицы и суффикса в конце имени, для примера таблицы Campaign и CampaignGGL, CampaignMSN и т.д.
Если таблица используется для хранения объектов определенных C#-классов, то ее имя должно совпадать с именем класса во множественном числе.
Если таблица используется для хранения объектов определенных C#-классов, то ее имя должно совпадать с именем класса во множественном числе.
- Имена индексов должны быть оформлены в стиле Camel. Не допускается использование пробелов или специальных символов в имени индекса таблицы, а также символов национального алфавита.
В имени индекса должны быть перечислены имена всех полей, входящих в выражение индекса, через символ «_».Если индекс включает в себя более пяти полей, достаточно в имени индекса перечислить первые 4-5 полей, и закончить строкой «_other».
- Имена кластерных индексов должны начинаться с префикса «idx_».
Имены некластерных индексов должны начинаться с «ndx_».
Имена primary key должны начинаться с префикса «pk_».
Пример:
CREATE CLUSTERED INDEX [idx_TrackDate] ON [dbo].[EventTracking]([TrackDate])
CREATE INDEX [ndx_HitGUID] ON [dbo].[EventTracking]([HitGUID]) ON [SECONDARY]
CREATE INDEX [ndx_SessionID_EventTypeID_TrackDate_VisitorID_Others] ON [dbo].[EventTracking]([SessionID], [EventTypeID], [TrackDate], [VisitorID], [Cost], [Profit])
CREATE INDEX [ndx_TrackDate_SessionID] ON [dbo].[EventTracking]([TrackDate], [SessionID])
CREATE CLUSTERED INDEX [idx_TrackDate] ON [dbo].[EventTracking]([TrackDate])
CREATE INDEX [ndx_HitGUID] ON [dbo].[EventTracking]([HitGUID]) ON [SECONDARY]
CREATE INDEX [ndx_SessionID_EventTypeID_TrackDate_VisitorID_Others] ON [dbo].[EventTracking]([SessionID], [EventTypeID], [TrackDate], [VisitorID], [Cost], [Profit])
CREATE INDEX [ndx_TrackDate_SessionID] ON [dbo].[EventTracking]([TrackDate], [SessionID])
- Ограничения (constraints) должны быть поименованы следующим образом:
Foreign key constraints: «Fk» + +
Defaults: «Df» +
Checks: «Ck» + <table name(Pascal case)> + <column name (Pascal case)>
Defaults: «Df» +
Checks: «Ck» +
- Имена представлений должны быть оформлены в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному его назначению, или же должно содержать в своем имени имя таблицы или имена таблиц, из которых происходит выборка данных.
Не допускается использование пробелов или специальных символов в имени представления, а также символов национального алфавита. Обязательно наличие префикса «v» в имени представления.
- Триггеры должны быть проименованы согласно следующим правилам:
Префикс «Tr» + <TableName> + <TriggerType>.
Если на одной таблице существует более одного триггера определенного типа, то в конце имени триггера добавляется порядковый номер такого триггера.
Для следующих типов триггеров определены следующие сокращения:
Insert – I
Update – U
Delete – D
Update – U
Delete – D
Например, триггеры на добавление, удаление и обновление для таблицы SomeTable должны быть поименованы таким образом:
TrSomeTableI,
TrSomeTableD,
TrSomeTableD2,
TrSomeTableU
TrSomeTableD,
TrSomeTableD2,
TrSomeTableU
- Полное имя объекта с использованием linked_server (четырехкомпонентные имена) формируется следующим образом:
LINKED_SERVER_NAME.Catalog.schema.ObjectName –
При этом имя linked_server-а указывается в upper-case, каталог(база данных) и имя объекта (таблица, хранимая процедура) указывается в стиле Pascal, имя схемы (владелец объекта) указывается в стиле lower-case.
- Имена хранимых процедур и функций должны быть оформлены в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному его назначению. Не допускается использование пробелов или специальных символов в имени хранимой процедуры, а также символов национального алфавита.
В общем случае имя хранимой процедуры, функции должно состоять из:
<[project name, task name, service name] prefix (camel case)> + «_» + <object name (Pascal case)> + <operation name (Pascal case)>;
- <[project name, task name, service name] prefix> - наименование проекта (применительно к c# solution) или процесса обработки данных, задачи, сервиса, в работе которой используется данная хранимая процедура или функция. Если это наименование подвергается сокращению, то даже сокращенное наименование должно быть понятным всем разработчикам, а не только разработчику данной процедуры, функции.
В качестве примера, если это вспомогательная процедура для поддержки логики работы всех остальных, то используется префикс [support], если используется в работе приложения MyApplication – то [myApplication] и т.д.
- <operation name> - название операции, которая применяется к <object name>. Если под операцией понимается какое-либо изменение конкретной таблицы, тогда допустимы следующие имена <operation name>.
- Get – возврат только одной строки;
- Select – возврат 1 и более строк или 1 и более наборов данных;
- Insert – Вставка в одну или более таблиц. Недопустимо возвращать из такой процедуры набор данных. Return code должен содержать признак 0 или 1 как признак удачного или неудачного выполнения;
- Update – Обновление данных в одной или более таблиц. Недопустимо возвращать из такой процедуры набор данных. Return code должен содержать признак 0 или 1 как признак удачного или неудачного выполнения;
- Delete – Удаление данных из одной или более таблиц. Недопустимо возвращать из такой процедуры набор данных. Return code должен содержать признак 0 или 1 как признак удачного или неудачного выполнения;
- <другой> - если операция не попала ни в одну из перечисленных;
Если под операцией понимается название какого-либо подпроцесса, логической операции, относящейся к группе таблиц – в этом случае необходимо использовать логическое наименование этого подпроцесса, операции – здесь допустимо как существительное (имя операции, например, backup), так и повелительное наклонение глагола (load, upload, remove и пр.).
- <object name> - это название объекта или группы объектов, над которым будет выполнена <operation name> - описанная выше операция. Это может быть как имя конкретной таблицы, так и логическое наименование любой сущности, которая имеет свое отражение в базе данных.
Пример:
- если в системе есть процесс MyProcess, которая делает backup каких-либо данных, то возможно такое наименование хранимой процедуры:
[dbo].[ myProcess_MyDataBackup];
- если тот же самый процесс имеет процедуры для добавления новой записи в справочник Dictionary, то возможно следующее наименование:
[dbo].[ myProcess_DictionaryInsert];
- если в пределах упомянутого процесса MyProcess мы хотим логически выделить другой подпроцесс, скажем, работу с какими-либо настройками, то возможно следующее наименование процедуры для операции, например, вставки данных в таблицу SomeTable:
[dbo].[ myProcessSettings_SomeTableInsert];
- если в системе есть процесс MyProcess, которая делает backup каких-либо данных, то возможно такое наименование хранимой процедуры:
[dbo].[ myProcess_MyDataBackup];
- если тот же самый процесс имеет процедуры для добавления новой записи в справочник Dictionary, то возможно следующее наименование:
[dbo].[ myProcess_DictionaryInsert];
- если в пределах упомянутого процесса MyProcess мы хотим логически выделить другой подпроцесс, скажем, работу с какими-либо настройками, то возможно следующее наименование процедуры для операции, например, вставки данных в таблицу SomeTable:
[dbo].[ myProcessSettings_SomeTableInsert];
- В тех случаях, когда возникает необходимость разнести код и логику хранимой процедуры (а эта необходимость возникает, как правило, в случаях разрастания кода), следует разбить исходную хранимую процедуру на несколько, придерживаясь следующего правила именования вновь создаваемых процедур:
Имя вновь созданной хранимой процедуры формируется как
<имя вызывающей хранимой процедуры> + «_» + <object name (Pascal case)> <operation name (Pascal case)>;
Оформление t-sql кода при написании user defined functions, stored procedures, triggers и прочих вспомогательных скриптов.
- Любой код в теле ветвлений, циклов, блоков кода должен быть выделен отступом размером один tab. Размер Tab Size принимается равным 4 пробела. Условие выражений if, while отделяем от данных инструкций символом tab таким образом, чтобы сам t-sql код внутри блоков был выравнен по началу условия ветвления, цикла,
Пример:
begin
if <condition>
begin
< condition body
...................
>
while <while_condition>
begin
< while loop body
........................
>
end
end
end
begin
if <condition>
begin
< condition body
...................
>
while <while_condition>
begin
< while loop body
........................
>
end
end
end
В любых операциях операнды должны быть отделены от операторов одним пробелом.
На примере операций присваивания, сравнения:
declare @variable int
set @variable = 1
if @variable <> 1
begin
...
end
set @variable = 1
if @variable <> 1
begin
...
end
В выражениях, в функциях, в операциях вызова хранимых процедур, функций, в любых сложных выражениях, все аргументы должны быть отделены от предыдущего значения запятой + <один пробел>, например:
select substring(convert(nvarchar(10), getdate(), 21), 1, 4)
- В запросах и подзапросах алиасы таблиц формируются путем сокращения имен участвующих в запросе таблиц, например, Users -> U и т.д.
- Все комментарии в коде необходимо оформлять, используя «--» + 1 tab symbol перед началом текста самого комментария. Если комментарий идет перед началом блока, сам текст комментария должен начинаться с той же позиции, что и t-sql код блока – т.е. символ начала комментарии «--» должен отставать от позиции начала блока на один tab size, для примера:
-- начало комментария
-- ...........................
if <condition>
begin
<condition body>
end
-- ...........................
if <condition>
begin
<condition body>
end
Для более удобного восприятия кода, содержащего большое количество ветвлений, а также блоков кода (begin/end), размер текста которого превышает размеры страницы, рекомендуется оформлять end-statement комментарием, содержащим или условие if-statement, или условие цикла (while), для примера:
-- начало комментария
-- ...........................
if <condition>
begin
< condition body
...................
>
while <while_condition>
begin
< while loop body
........................
>
end -- while <while_condition>
end -- if <condition>
-- ...........................
if <condition>
begin
< condition body
...................
>
while <while_condition>
begin
< while loop body
........................
>
end -- while <while_condition>
end -- if <condition>
- Ко всем встроенным инструкциям t-sql языка программирования в коде хранимых процедур, триггеров, пользовательских функций должен применяться стиль оформления lower-case. Это относится как к select, insert, update, delete, create и прочим инструкциям, так и к выховам extended stored procedures и встроенным функциям (substring(), getdate() и пр.).
К пользовательским объектам базы данных должен применяться стиль оформления Pascal, т.е. к пользовательским функциям, хранимым процедурам, именам таблиц и пр.
Стиль оформления Pascal должен применяться также и при работе с локальными переменными.
Стиль upper-case должен применяться только в alter-скриптах и только применительно к инструкциям create, select, update, delete, insert.
- При создании хранимой процедуры после ее имени с новой строки после объявления ее параметров должна быть указана в комментариях следующая информация:
- дата создания,
- кем была создана процедура
- ее назначение.
После каждого какого-либо существенного изменения эти изменения должны быть также зафиксированы в истории работы над кодом хранимой процедуры.
Комментарий о произведенных изменениях оформляется аналогично оформлению комментария о назначении процедуры (Все комментарии оформляются согласно стилю оформления комментариев) .
Пример:
ALTER PROCEDURE [dbo].[support_LostDBRecordsProcessor]
@Dir nvarchar(100) = 'c:\logs\LostDBRecords',
@FileExtension nvarchar(100) = '*.txt',
@DateFormat nvarchar(10) = 'dmy'
-- 2010.02.07 created by smirnov a
-- lost db records processor implementation
-- This procedure must scan ..\Logs\LostDBRecords directory and execute
-- the bulk insert operation for current
-- database and after that create .cab archives or create a .log file for a
-- corresponding file in case of an error
-- 2010.04.06 modified by smirnov a
-- sql server version analisys was added. If @version variable equals 2005, we must
-- remove the "nooutput" parameter from xp_cmdShell
AS
begin …
@Dir nvarchar(100) = 'c:\logs\LostDBRecords',
@FileExtension nvarchar(100) = '*.txt',
@DateFormat nvarchar(10) = 'dmy'
-- 2010.02.07 created by smirnov a
-- lost db records processor implementation
-- This procedure must scan ..\Logs\LostDBRecords directory and execute
-- the bulk insert operation for current
-- database and after that create .cab archives or create a .log file for a
-- corresponding file in case of an error
-- 2010.04.06 modified by smirnov a
-- sql server version analisys was added. If @version variable equals 2005, we must
-- remove the "nooutput" parameter from xp_cmdShell
AS
begin …
Те же самые правила относятся к оформлению user defined functions с той лишь разницей, что комментарии о создании, внесении изменений вносятся после объявления параметров.
История изменений должна логически подниматься вверх по коду таким образом, чтобы последний комментарий о внесенном изменении был всегда сверху над остальными, НО после первого комментария о создании процедуры, функции, триггера. Таким образом, при чтении кода сразу видим назначение процедуры, ее первоначального автора, и информацию о самом последнем изменении.
Пример:
ALTER PROCEDURE [dbo].[support_SearchDDLChanges]
@TableName nvarchar(100) = null
-- 2010.01.01 created by <author>
-- Данная процедура предназначена для выполнения операции сравнения
-- DDL описаний таблиц из указанной базы данных по сравнению с эталонной
-- 2010.03.01 modified by <changes_author>
-- bugfix 0001 - скрипт неправильно работал
-- 2010.02.01 modified by <changes_author>
-- Добавлена функциональность по автоматическому обновлению структуры
-- указанной базы данных
-- ....
AS
@TableName nvarchar(100) = null
-- 2010.01.01 created by <author>
-- Данная процедура предназначена для выполнения операции сравнения
-- DDL описаний таблиц из указанной базы данных по сравнению с эталонной
-- 2010.03.01 modified by <changes_author>
-- bugfix 0001 - скрипт неправильно работал
-- 2010.02.01 modified by <changes_author>
-- Добавлена функциональность по автоматическому обновлению структуры
-- указанной базы данных
-- ....
AS
Если имеет смысл указать в самом t-sql коде, в каком именно месте были произведены изменения, перед новым или измененным выражением стоит поставить комментарий в таком формате, как и в истории изменений, если не требуется - без описания произведенных изменений.
-- <date> modified by <author>
-- bugfix <bug number> or additional description
insert into ....
- Параметры хранимой процедуры, функции должны быть именованы в стиле Pascal и нести осмысленный логический смысл. Объявление параметра должно начинаться с новой строки с отступом 1 tab size. Если смысл параметра непонятен, после объявления ее типа, значения по умолчанию (если есть) должен быть комментарий о назначении данного параметра. Если комментарий не убирается в пределах окна редактирования по ширине, его необходимо сделать многострочным, применяя следующий стиль оформления:
@FullDatabasePathLogs nvarchar(100) = 'dbo',
-- Полный путь к базе данных (linked_server.catalog.owner),
-- откуда будем брать нормализованные логи для обработки
@FullDatabasePathReports nvarchar(100) = 'MyServer.MyDB.dbo'
-- Полный путь к базе данных (linked_server.catalog.owner), -- на котором будут храниться отчеты - MyServer.MyDB.dbo
-- Полный путь к базе данных (linked_server.catalog.owner),
-- откуда будем брать нормализованные логи для обработки
@FullDatabasePathReports nvarchar(100) = 'MyServer.MyDB.dbo'
-- Полный путь к базе данных (linked_server.catalog.owner), -- на котором будут храниться отчеты - MyServer.MyDB.dbo
- К выражениям select необходимо применять следующий стиль оформления: имя каждого выражения (операции над column), поля должно быть на отдельной строке; каждое следующее выражение, поле должно начинаться с начальной позиции предыдущего; первое выражение, поле должно быть отделено от select statement отступом 1 tab size, как в примере ниже:
select column_01,
expression(column_02, operand_01, operand_02, ..),
column_03
Выражения from, join, where, order, group, having должны быть на одном уровне с выражением select. К перечисленным выражениям инструкции select применяем такие же правила, т.е. остальную часть подвыражений отделяем отступом в 1 tab size.
Если условие в where clause, join clause состоит из нескольких логических выражений, то каждое такое логическое выражение должно начинаться с новой строки, причем сам логический оператор (Boolean expressions and, or, not), связывающий эти выражения в условии, должен быть вначале перенесенного выражения.
Если условие в where clause, join clause состоит из нескольких логических выражений, то каждое такое логическое выражение должно начинаться с новой строки, причем сам логический оператор (Boolean expressions and, or, not), связывающий эти выражения в условии, должен быть вначале перенесенного выражения.
Условие связывания таблиц в join-ах (on-expression) должно записываться следующим образом: сначала указывается имя поля из той таблицы (или алиаса) , по которой описывается join filter (собственно, указывается в join on <table_name>), затем значение самого фильтра.
Все вышеперечисленное можно показать на примере:
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
from table_01
join table_01 on table_01.column_01 = table_02.column_01
and <boolean expression>
join table_nn on table_nn.column_03 = table_02.column_03
where table_01.column_03 not in (..... )
and <where boolean expression 01>
or <where boolean expression 02>
group by table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
having count(*) > 10
order by table_01.column_01
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
from table_01,
table_02,
table_nn ............
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
from table_01
join table_01 on table_01.column_01 = table_02.column_01
and <boolean expression>
join table_nn on table_nn.column_03 = table_02.column_03
where table_01.column_03 not in (..... )
and <where boolean expression 01>
or <where boolean expression 02>
group by table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
having count(*) > 10
order by table_01.column_01
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03
from table_01,
table_02,
table_nn ............
- В выражении insert into список полей в выражении insert указывается одной строкой, если список не убирается в одну строку, переносится так, чтобы список был виден в пределах ширины страницы.
Into statement должен начинаться с той же позиции, что и список полей из select_list из выражения select.
Select statement оформляется согласно описанным выше правилам.
Пример:
insert into <destination_table> (field_01, field_02, field_03, field_04,...., field_nn)
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03,
.....
....................................
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03,
.....
into <destination_table>
....................................
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03,
.....
....................................
select count(*),
table_01.column_01,
expression(table_01.column_02, operand_01, operand_02, ..),
table_02.column_03,
.....
into <destination_table>
....................................
- Для операций update, delete применяются те же правила, что и при оформлении select, insert выражений, т.е. операции присваивания над полями таблицы должны быть отделены от set на 1 tab size, каждая операция set в update-выражении должна начинаться с новой строки и начинаться с той же позиции, что и предыдущая. Операнды в операции присваивания должны быть отделены одним пробелом или tab от символа «=» (смотри рекомендации по отступам).
Сразу же за ключевым словом update или delete должен идти один tab, список обновляемых полей в выражении update должен быть на одном уровне с именем таблицы, так же как и само условие в выражении where. При описании where-условия придерживаемся тех же правил, что и при написании select statement.
Пример:
update <SourceTable>
set <Column_01> = <value01>,
<Column_02> = <value02>,
<Column_nn> = <valueNN>
where <condition_01>
and <condition_02>
delete from <SourceTable>
where <condition_01>
and <condition_02>
- Выражение create table оформляется таким образом, чтобы описание каждого поля начиналось с новой строки. Желательно форматировать список колонок таким образом, чтобы типы данных находились один над другим, т.е. применяем колоночный стиль оформления.
Пример:
create table <table_name> ( Column_01 int identity (1, 1) primary key,
Column_02 nvarchar(100) not null,
Column_03 bit null,
CreateDate datetime default (getdate()) )
Column_02 nvarchar(100) not null,
Column_03 bit null,
CreateDate datetime default (getdate()) )
- При объявлении курсора select statement должно начинаться с новой строки с той позиции, с которой начинается описание типа переменной курсора. К оформлению select statement применяются все вышеописанные правила.
declare columns_list cursor local forward_only for
select <column_01>,
<column_02>,
<column_nn>
from <source_table>
where <where_condition>
declare @Columns_list cursor
set @Columns_list = cursor local forward_only for
select <column_01>,
<column_02>,
<column_nn>
from <source_table>
where <where_condition>
- При объявлении в t-sql коде переменных желательно придерживаться табличного стиля оформления, т.е. типы данных переменных должны начинаться с одной определенной позиции, имена переменных аналогично, приблизительно как показано ниже:
declare @Variable_01 int,
@Variable_02 nvarchar(100),
@Variable_04 bit
-- или
declare @Variable_01 int
declare @Variable_02 nvarchar(100)
declare @Variable_04 bit
Общие рекомендации.
Переменные.Все переменные необходимо объявлять в начале блока, в котором они используются: метода, цикла, ветвления и пр.
Временные таблицы малого объема сохранять в памяти (вместо # - @), кроме тех случаев, когда это накладывает неприемлемые ограничения.
Т.е. вместо create table #temp (ID int)
использовать declare @temp table (ID int)
Требования, обязательные к применению.
- Необходимо создавать связи для всех таблиц в базе данных.
- Все таблицы должны быть отражены на соответствующих диаграммах.
- Поля с допустимым значением NULL допускается использовать только в тех случаях, когда значение NULL несет логическое значение и не может быть заменено другим.
- При добавлении новых полей допустимость значения NULL определяется в соответствии с предыдущим правилом.
- Необходимо использовать типы минимально необходимого размера.
- Для операции select необходимо указывать только те поля, которые требуются в данном запросе.
Пример:
select ID, Keyword
select ID, Keyword
from KeywordParams (nolock)
- Именование таблиц статусов: Имя статуса(с большой буквы)+Statuses.
Пример:
UserStatuses
UserStatuses
- Идентификаторы записей во всех таблицах должны называться ID.
Пример:
в таблице Users поле идентификатора должно называться ID, а не UserID.
в таблице Users поле идентификатора должно называться ID, а не UserID.
- Идентификаторы в статических таблицах (справочниках) не должны быть помечены как identity.
- Ссылки на идентификаторы других таблиц именуются: Имя таблицы в единственном числе+ID.
Пример:
Если таблица Events ссылается на UserStatuses,
то поле внешнего ключа должно называться UserStatusID, а не StatusID.
Если таблица Events ссылается на UserStatuses,
то поле внешнего ключа должно называться UserStatusID, а не StatusID.
- Для всех запросов, где участвуют таблицы, которые не подвергаются изменению, в запросах select необходимо использовать (nolock) для каждой такой таблицы.
Пример:
select Keyword, KP.ID
from Keywords (nolock),
KeywordParams KP (nolock)
where Keywords.ID = KP.KeywordID
select Keyword, KP.ID
from Keywords (nolock),
KeywordParams KP (nolock)
where Keywords.ID = KP.KeywordID
- Для update запросов, которые обрабатывают одну запись необходимо использовать (rowlock, updlock) для каждой таблицы, в которой происходит update.
Пример
update Keywords with (rowlock, updlock)
set Keyword = 'text'
from Keywords
where Keywords.ID = 123
update Keywords with (rowlock, updlock)
set Keyword = 'text'
from Keywords
where Keywords.ID = 123
Спасибо, именно то что искал!
ОтветитьУдалитьНе понятен смысл updlock в
ОтветитьУдалитьupdate Keywords with (rowlock, updlock)
это лишнее, запрос
update Keywords with (rowlock)
даст те же блокировки