|
Программирование >> Программирование баз данных
В рассматриваемом примере можно было бы легко обойтись без промежуточной передачи значения @@IDENTITY в локальную переменную, поскольку достаточно было бы просто явно сослаться на это значение в следующем операторе INSERT. Но автор усвоил привычку всегда передавать полученное значение в локальную переменную, чтобы избежать ошибок, которые могут возникать в тех случаях, если действительно нужна копия данных. В качестве примера такой ситуации можно указать применение еще одного оператора INSERT, зависящего от идентификационного значения, которое получено после применения оператора INSERT для вставки данных в таблицу Orders. Если бы полученное перед этим идентификационное значение не было перенесено в локальную переменную, то после выполнения следующей операции INSERT оно было бы потеряно, в связи с тем, что произошла бы его перезапись значением, полученным при вставке данньгх в таблицу Details. Если же таблица, применительно к которой выполняется следующая операция вставки, не имеет столбца идентификации (а таковыми являются большинство дочерних таблиц, применяемых при этом способе организации взаимодействия таблиц), то системная переменная ©©IDENTITY приобретает NULL-значение. Кроме того, передача значения ©©IDENTITY в локальную переменную позволяет сохранить это значение на тот случай, если придется в дальнейшем вывести его на печать для справок. Использование системной переменной @@rowcount При выполнении многочисленных запросов, которые рассматривались до сих пор в данной книге, всегда было довольно легко узнать, какое количество строк затронуто тем или иным оператором, В частности, информация об этом могла быть получена с помощью программы Management Studio. Например, после вызова на выполнение оператора USE AdventureWorks SELECT LastName FROM Person.Contact; (290 row(s) affected) Ho иногда требуется определить количество строк, затронутьгх конкретным запросом, программным путем. Кроме ©©IDENTITY, еще одним бесценным инструментальным средством, позволяющим определить, что происходит в сценарии, является системная переменная ©©ROWCOUNT, но данная переменная возвращает значение, которое указывает количество затронутых строк, а не идентификационное значение. Рассмотрим с помощью следующего примера, как применяется эта системная переменная на практике: USE AdventureWorks GO DECLARE ©RowCount int Обратите внимание на наличие лишь одного знака @ SELECT * FROM HumanResources.Employee SELECT ©RowCount = ©©ROWCOUNT PRINT The value of ©©ROWCOUNT was + CAST(©RowCount AS varchar(5)) Этот сценарий также показывает количество возвращенных строк, но, кроме того, в полученном выводе появляется новая строка: The value of ©©ROWCOUNT was 2 90 Приведенный выше пример также показывает, что и значение @@ROWCOUNT желательно сохранять во вспомогательной переменной, во многом аналогично тому, как сохраняется значение ©©IDENTITY. Дело в том, что значение ©©ROWCOUNT переустанавливается после вьшолнения каждого следующего оператора, поэтому если значение @®ROWCOUNT, полученное на каком-то этапе, в дальнейшем будет использоваться для осуществления целого ряда действий, то его следует перенести в безопасное место. Пакеты Пакет - это средство группирования операторов T-SQL в виде одной логической единицы. Все операторы, содержащиеся в пакете, объединяются в один план вьшолнения, поэтому в процессе синтаксического анализа рассматриваются все операторы, которые должны успешно пройти проверку синтаксиса, так как в противном случае не будет выполнен ни один из операторов. Тем не менее следует отметить, что успешное завершение проверки синтаксиса не исключает возможности возникновения ошибок на этапе прогона. В случае возникновения ошибки этапа прогона все еще сохраняются результаты всех операторов, которые были выполнены до этой ошибки. Иначе говоря, если синтаксический анализ одного из операторов завершается неудачей, то вызов пакета не происходит, а если неудачей завершается попытка вьшолнения одного из операторов на этапе прогона, то отмена действия всех операторов, предшествующих неудачно завершившемуся оператору в пакете, не происходит. Все сценарии, рассматривавшиеся нами до сих пор, можно считать отдельными пакетами. Одним пакетом считается даже тот большой сценарий, описание которого приведено выше в данной главе. Чтобы разделить сценарий на несколько пакетов, можно воспользоваться оператором GO. Оператор GO характеризуется описанными ниже особенностями. Этот оператор должен находиться на отдельной строке (на той же строке не должно быть больше ничего, за исключением комментариев); из этого правила есть исключение, которое будет вскоре описано, но следует всегда исходить из того, что оператор GO должен находиться на отдельной строке. Оператор GO вызывает компиляцию всех операторов от начала сценария или от предыдущего оператора GO (в зависимости от того, что ближе), после чего полученный план вьшолнения передается на сервер независимо от всех других пакетов. Оператор GO - это не оператор языка T-SQL, а скорее команда, распознаваемая различными утилитами SQL Server с интерфейсом командной строки (OSQL, ISQL и Query Analyzer). Оператор go, расположенный на отдельной строке Оператор GO должен находиться на отдельной строке. С формальной точки зрения определение нового пакета может начинаться на той же строке, где находится оператор GO, вслед за этим оператором, но в таком случае удобство чтения значительно снижается. Кроме того, перед оператором GO в той же строке не могут находиться другие операторы T-SQL, так как это часто приводит к получению ошибочных результатов синтаксического анализа и может либо вызвать ошибку синтаксического анализа, либо привести к возникновению других непредвиденных ситуаций. Например, синтаксический анализатор, встретив оператор GO после конструкции WHERE, как показано в следующем примере: SELECT * FROM Customers WHERE CustomerlD = 2 GO выводит сообщение об ошибке: Msg 102, Level 15, State 1, Line 1 Incorrect syntax near GO. Отдельная отправка каждого пакета на сервер Каждый пакет обрабатывается независимо от других пакетов, поэтому ошибка при выполнении одного пакета не исключает возможности успешного выполнения другого пакета. В качестве иллюстрации рассмотрим следующий пример кода: USE AdventureWorks DECLARE ©MyVarchar varchar(50) -- Действие этого оператора DECLARE -- распространяется только на данный пакет!! SELECT ©MyVarchar = Honey, Im home... PRINT Done with first Batch... PRINT ©MyVarchar При выполнении этого оператора возникает ошибка, поскольку -- переменная ©MyVarchar не объявлена в данном пакете PRINT Done with second Batch PRINT Done with third batch -- Следует отметить, что этот пакет выполняется, несмотря на то, что перед этим возникла ошибка Если бы между пакетами, содержащимися в этом коде, имелись зависимости, то происходило бы аварийное завершение сразу всех пакетов из-за ошибки во втором пакете или по крайней мере окончилось бы неудачей выполнение и этого пакета, и всех следующих, но этого не происходит, как показывают следующие результаты выполнения приведенного выше сценария: Done with first Batch... Msg 137, Level 15, State 2, Line 2 Must declare the scalar variable ©MyVarchar . Done with third batch Эти результаты подтверждают, что каждый пакет является полностью автономным с точки зрения влияния на него нарушений в работе, возникающих на этапе прогона. Но следует помнить, что зависимости между пакетами могут возникать исходя из того, что в одном пакете будет предприниматься попытка выполнить работу, зависящую от результатов успешного выполнения предьщущего пакета. Дополнительная информация на эту тему приведена в следующем разделе, в котором речь идет о том, какая информация передается и не передается из одного пакета в другой.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |