Показаны сообщения с ярлыком SQL Server. Показать все сообщения
Показаны сообщения с ярлыком SQL Server. Показать все сообщения

суббота, 7 марта 2015 г. - www.msmirnov.ru

Концепция автоматизированной системы управления физическим размещением данных на MS SQL Server

В этом материале я хочу рассказать о принципиальной структуре и концепции системы управления физическим расположением данных, построенной на базе MS SQL Server.
Данную концепцию можно использовать при наличии задачи построения системы подобного рода. Я надеюсь, что материал окажется полезным тем, кто сам столкнется с такой тематикой. Если по прочтении статьи у кого-либо появится потребность в более детальном рассмотрении тех или иных вопросов построения такой системы, я буду рад это сделать.

Основной задачей такой системы является сокрытие от конечного пользователя физического места расположения данных, управление их физическим расположением, обслуживание данных, мониторинг состояния и т.п.

Систему необходимо строить так, чтобы пользователь (человек или процесс), выполняя запросы на получение или запись данных, не знал о том, где физически они хранятся - система должна скрывать их физическое расположение и сама решать вопросы распределения данных и выдачи их пользователю.

Структуру такой системы можно изобразить на диаграмме:



Как видно на диаграмме, система разделена на 4 части:
  • Управление расположениями - часть системы, отвечающая за создание, удаление, подготовку к использованию и обслуживание хранилищ данных.  Именно эта часть система отвечает за управление физическим расположением данных.
  • Подсистема безопасности - часть системы, ответственная за управление правами доступа к данным.
  • Интерфейс администрирования - часть системы, предоставляющая администратору возможность управлять ее работой.
  • API - программный интерфейс системы, позволяющий сторонним приложениям получать доступ к хранящимся данным.
Все данные, расположением которых управляет такая система, можно разделить на типы.
Типом данных может быть что угодно, например - список клиентов, история заказов, история просмотров - в общем, что угодно.
Каждый тип данных при этом обладает своей структурой - списком атрибутов, определяющих какие именно данные хранит каждый тип.


Задачи подсистемы "Интерфейс администрирования".
  1. Позволять регистрировать в системе новые типы данных, определять их структуру (имена атрибутов, их типы и другие свойства).
  2. Регистрировать в системе новые физические сервера для размещения данных
  3. Задавать настройки расположение данных на каждом сервере
  4. Управлять настройками распределения данных между серверами
  5. Управлять настройками прав доступа

Задачи подсистемы "Управление расположением".
  1. Заблаговременно и по требованию пользователя создавать на физических серверах базы данных, таблицы, элементы партицирования и пр. для размещения данных
  2. Исправлять ошибки, возникающие в процессе работы - обрывов связи, сбоев в работе серверов и т.п.
  3. Проводить публикацию новых данных, если она требуется
  4. Выполнять дефрагментацию и переиндексацию
  5. Удалять устаревшие данные
  6. Управлять распределением данных между серверами

Задачи подсистемы безопасности.
  1. Управление доступом на запись и чтение данных
  2. Управление пользовательскими сессиями, мешающими работе с данными


Задачи подсистемы API.
  1. Выдавать конечным потребителям данные, хранящиеся в системе
  2. Принимать от потребителей новые данные, которые необходимо поместить в систему
  3. Получать от потребителей сигналы о необходимости выполнения публикации переданных данных
  4. Обеспечение параллельной работы пользователей с системой

В заключении хочу сказать что тема построения таких систем весьма обширна и здесь даны лишь самые общие наброски в направлении их создания.

Мой сайт - www.msmirnov.ru

пятница, 25 мая 2012 г. - www.msmirnov.ru

Желаемый синтаксический сахар в Microsoft SQL Server

Версия MS SQL 2012, конечно, несет много интересных доработок.

Однако, меня давно интересует, почему в SQL Server'е не добавить немного синтаксического сахара относительно курсоров.

В самом деле, если бы у нас была возможность пробегаться по курсорам при помощи конструкций примерно следующего вида, то было бы намного проще:

foreach MyRow in (select * from MyTable)
    begin
        select MyField from MyRow
    end


Сейчас, для того, чтобы сделать тоже самое, нам приходится постоянно набирать куски кода вроде этого:

declare @MyField int
   
declare cur cursor for
select MyField from MyTable

open cur

fetch next from cur into @MyField

while @@FETCH_STATUS = 0
    begin
        select
@MyField
       
        fetch next from cur into @MyField
    end

close cur
deallocate cur

Который по своему функционалу аналогичен предыдущему, но как видно, намного длиннее.

Я понимаю, что есть разные виды курсоров. способы их обхода и пр.
Но все-же для наиболее часто употребляемого случая - когда мы используем локальный курс с движением только вперед - такой синтаксический сахар был бы очень полезен.

Кроме того, его можно было бы дополнить и различными настройками курсора, если уж это может кому-то потребоваться.

Прощу представителей компании Microsoft, в случае прочтения данного сообщения, считать это моим личным пожеланиям относительно новой функциональности в дальнейших версиях SQL Server.
Мой сайт - www.msmirnov.ru

четверг, 18 августа 2011 г. - www.msmirnov.ru

Как заставить работать filtered indexes в MS SQL Server 2008.

Недавно мы столкнулись со следующей проблемой – создали несколько filtered indexes, которые не хотели работать – оптимизатор не хотел их использовать, даже если условия запроса удовлетворяли условиям индекса.

В Books online проблема описана довольно скупо, но вот что удалось выяснить – для нормальной работы filtered indexes необходимо произвести те же настройки, которые нужны для indexed views или indexed computed columns, а именно (http://msdn.microsoft.com/en-us/library/ms175088.aspx):

ANSI_NULLS ON
ANSI_PADDING ON
ANSI_WARNINGS ON
ARITHABORT ON
CONCAT_NULL_YIELDS_NULL ON
NUMERIC_ROUNDABORT OFF
QUOTED_IDENTIFIER ON

После включения этих опций filtered indexes начинают работать как надо.
Мой сайт - www.msmirnov.ru

вторник, 26 июля 2011 г. - www.msmirnov.ru

Работа со старыми DTS-пакетами MS SQL Server 2000 в MS SQL Server 2008

Недавно мне пришлось столкнуться с необходимостью работы с набором DTS-пакетов, созданных много лет назад в MS SQL Server 2000 и импортированных в SQL Server 2008.

Отказаться от их использования было нельзя - приложение было написано очень давно и задачи перехода на SSIS не стояло.

SQL Server 2008 обеспечивает корректную работу старых DTS-пакетов, но вот Management Studio 2008 не открывает DTS-пакеты для просмотра и редактирования, выдавая следуюшую ошибку:

"SQL Server 2000 DTS Designer components are required to edit DTS packages. Install the special Web download, “SQL Server 2000 DTS Designer Components” to use this feature. "


Microsoft предлагает скачать и установить SQL Server 2000 DTS Designer Components - см. здесь - (для этого надо будет скопировать 6 файлов (SEMSFC.DLL, SQLGUI.DLL, SQLSVC.DLL, SEMSFC.RLL, SQLGUI.RLL, и SQLSVC.RLL) из установки SQL Server 2000 в каталог с SQL Server 2008).

Однако, это  не решит проблему для случая SQL Server 2008 - после копирования файлов Server 2000 DTS Designer будет запускаться из Management Studio 2008, но корректно работать все равно не будет. Этот способ работает только для случая SQL Server 2005.

В SQL Server 2008 будет выдаваться следующая ошибка:

"Error Source : Microsoft Data Transformation Services (DTS) Package
Error Description : The DTS host failed to load or save the package properly.
"


В Microsoft пока не создали решения этой проблемы для SQL Server 2008, но есть один обходной вариант - пусть не очень удобный, но в случае необходимости он работает.

Следует поставить старый добрый SQL Server 2000 - причем не только сам Enterprise manager, а и ядро сервера - без инстанса работать с DTS-пакетами не получиться.
Причем, ставить нужно SQL Server 2000 SP3 или SP4. С SP2 работать не будет.

После этого необходимо сохранить DTS-пакеты из Management Studio 2008 на диск и открыть файлы на редактирование в Enterprise manager. Сам инстанс SQL 2000 при этом не понадобиться - Enterprise manager будет просто работать с файлами. Затем файлы необходимо опять импортировать в SQL Server 2008.

Способ не очень удобный - каждый DTS-пакет приходится каждый раз гонять туда-сюда, но он работает и поскольку ничего другого сейчас все равно нет - приходится пользоваться таким.

Хорошей новостью является то, что DTS-пакетами можно при этом управлять без каких-либо ограничений, так параметры подключений, которые в них указаны, в этом случае подключаются, как правило не к текущему серверу, а к SQL Server 2008, что облегчает работу с ними.
Мой сайт - www.msmirnov.ru

четверг, 13 января 2011 г. - www.msmirnov.ru

Стандарты и правила оформления кода C# и T-SQL

Последнее время меня несколько раз спрашивали относительно стандартов и правил оформления кода на C# и T-SQL , поэтому я решил выложить их в открытый доступ.

Стандарты и правила доступны по следующим ссылкам на моем сайте:
Мой сайт - www.msmirnov.ru

среда, 12 января 2011 г. - www.msmirnov.ru

Стандарты и правила оформления кода T-SQL

Последнее время меня несколько раз спрашивали относительно стандартов и правил оформления кода на T-SQL , поэтому я решил выложить их в открытый доступ.

Для загрузки Стандарты и правила доступны по следующий ссылке на моем сайте: 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#-классов, то ее имя должно совпадать с именем класса во множественном числе.


  • Имена индексов должны быть оформлены в стиле 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])

  • Ограничения (constraints) должны быть поименованы следующим образом:

Foreign key constraints: «Fk» + +

Defaults: «Df» +

Checks: «Ck» +
<table name(Pascal case)> + <column name (Pascal case)>



  • Имена представлений должны быть оформлены в стиле Pascal, нести осмысленное и логическое назначение и отвечать основному его назначению, или же должно содержать в своем имени имя таблицы или имена таблиц, из которых происходит выборка данных.
    Не допускается использование пробелов или специальных символов в имени представления, а также символов национального алфавита. Обязательно наличие префикса «v» в имени представления.

  • Триггеры должны быть проименованы согласно следующим правилам:
    Префикс «Tr» + <TableName> + <TriggerType>.

    Если на одной таблице существует более одного триггера определенного типа, то в конце имени триггера добавляется порядковый номер такого триггера.
Для следующих типов триггеров определены следующие сокращения:

Insert – I
Update
– U
Delete
– D


Например, триггеры на добавление, удаление и обновление для таблицы SomeTable  должны быть поименованы таким образом:

TrSomeTableI,
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];

  • В тех случаях, когда возникает необходимость разнести код и логику хранимой процедуры (а эта необходимость возникает, как правило, в случаях разрастания кода), следует разбить исходную хранимую процедуру на несколько, придерживаясь следующего правила именования вновь создаваемых процедур:

    Имя вновь созданной хранимой процедуры формируется как
<имя вызывающей хранимой процедуры> + «_» + <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

В любых операциях операнды должны быть отделены от операторов одним пробелом.
На примере операций присваивания, сравнения:


declare        @variable        int
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

Для более удобного восприятия кода, содержащего большое количество ветвлений, а также блоков кода (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>



  • Ко всем встроенным инструкциям 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
       …

Те же самые правила относятся к оформлению 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

Если имеет смысл указать в самом 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


  • К выражениям 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), связывающий эти выражения в условии, должен быть вначале перенесенного выражения.


Условие связывания таблиц в 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 ............

  • В выражении 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>      
....................................

  • Для операций 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())        )



  • При объявлении курсора 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

from        KeywordParams (nolock)

  • Именование таблиц статусов: Имя статуса(с большой буквы)+Statuses.
Пример:
                        UserStatuses


  • Идентификаторы записей во всех таблицах должны называться ID.
Пример:
               в таблице Users поле идентификатора должно называться ID, а не UserID.


  • Идентификаторы в статических таблицах (справочниках) не должны быть помечены как identity.

  • Ссылки на идентификаторы других таблиц именуются: Имя таблицы в единственном числе+ID.

Пример:
                     Если таблица Events ссылается на UserStatuses,
                     то поле внешнего ключа должно называться UserStatusID, а не StatusID.

  • Для всех запросов, где участвуют таблицы, которые не подвергаются изменению, в запросах select необходимо использовать (nolock) для каждой такой таблицы.

Пример:

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



Мой сайт - www.msmirnov.ru