    18 ГЛАВА 

    Sybase SQL Server 

    Э та глава посвящена системе управления реляционными базами данных 
Microsoft SQL Server. Здесь обсуждаются вопросы совместного использования SQL 
Server и Delphi, а также кратко рассматривается диалект Transact-SQL системы 
Sybase SQL Server. 

    Запуск сервера 

    Способы запуска и завершения работы СУБД Sybase SQL Server неодинаковы в 
различных операционных системах. В системе UNIX для запуска сервера 
используется сценарий КШ_имя-сервера, а в системе Windows NT — приложение 
Sybase Services Manager. Эта утилита находится в программной группе или папке 
Sybase SQL Server. Можно использовать также аплет Services папки Control Panel 
Windows NT. Поскольку SQL Service функционирует в качестве службы Windows NT, 
ее можно запускать и останавливать с помощью команды Services приложения 
Windows NT Service Manager. 
    Кроме средств управления SQL Server как службой Windows NT, для завершения 
ее работы при необходимости можно использовать команду SHUTDOWN языка 
Transact-SQL. Для немедленного завершения работы сервера в команде SHUTDOWN 
необходимо указать параметр NOWAIT. В противном случае работа сервера 
завершается после завершения текущего процесса. 

    Подключение к серверу 

    Для подключения клиентных приложений Delphi, работающих под управлением 
Windows 95 или Windows NT, к серверу Sybase необходимо установить программный 
пакет Sybase Net Library. Существуют две версии этого пакета для семейства 
операционных систем Windows 95 и Windows NT, причем они существенно отличаются 
одна от другой. Версия для Windows NT (поставляемая в составе пакета Sybase 
Open Client for Windows NT) может быть установлена только в этой операционной 
системе. Ее нельзя установить и запустить в системе Windows 95 — попытка 
установки закончится сообщением об ошибке номер 422. 
    Вторая версия может быть установлена как в Windows 95, так и в Windows NT. 
Эту версию можно узнать по информационному сообщению на заставке. Она написана 
позже, чем первая версия, и по причине совместимости с двумя операционными 
системами предпочтительнее использовать именно ее. 

    Ошибка 422 пакета Net Library/Open Client в системе Windows NT 

    Версия пакета Net Library для Windows NT имеет одну непривлекательную 
особенность: иногда ее установка в системе проходит некорректно. В версии 
начала 1996 г. программа установки часто генерировала сообщение об ошибке 
номер 422, даже в системе Windows NT. Оказывается, что эта проблема решается 

    Глава 18. Sybase SQL Server 371 

    несложно. Несмотря на то, что инструкция, прилагающаяся к программе, 
требует удалить все файлы из каталога TEMP системы Windows перед установкой 
пакета, оказывается, что необходимо поступить как раз наоборот. Если программа 
установки аварийно завершается с сообщением об ошибке 422, то в каталоге TEMP 
остается несколько временных файлов. Запустите программу установки еще раз, не 
удаляя эти фаллы, и на этот раз все пройдет нормально. 

    Настройка клиента 

    Для настройки параметров подключения клиентного приложения используется 
программа SQLEDIT независимо от версии пакета Net Library. Для настройки 
параметров подключения к серверу выполните следующие операции. 
    1.Запустите программу SQLEDIT и введите имя сервера баз данных в строке 
Input Server Name. 
    2.Щелкните на кнопке Add для добавления введенного имени в список Server Entry. 
    3.Раскройте список Service Type и выберите из него пункт Query. 
    4.В списке Platform выберите Windows 95 или Windows NT в зависимости 
от используемой операционной системы. 
    5.В списке Net-Library Driver выберите сетевой драйвер. Наиболее 
распространенными драйверами являются NLWNSCK (для протокола TCP/IP Winsock) и 
NLNWLINK (для протокола IPX).     
    6.Введите сетевой адрес и номер порта сервера, разделяя их запятыми, в 
строке Connection Information/Network Address. Это должен быть TCP/IP-адрес 
для протокола TCP/IP или сетевой IPX-номер для протокола IPX. Вот пример 
строки, описывающей подключение: 
    100.10.15.12,3000 
    В данном примере 100.10.15.12 — сетевой адрес TCP/IP, а   3000 — номер 
порта. Если адрес или номер порта сервера неизвестны, следует обратиться к 
администратору сети или системы. 

    На заметку 
    Вместо фактических адресов TCP/IP в качестве параметров соединений можно 
использовать обозначения записей файла HOSTS. Например, если в файле HOSTS 
имеется следующая запись: 
    100.10.15.12    marketing 
    то в строке параметров соединения можно указать marketing, 3000. 
    7.    После ввода информации о параметрах подключения щелкните на кнопке 
Add Service для добавления службы в список Connection Service Entry. 
    8.   После добавления службы необходимо протестировать ее 
работоспособность. Для этого щелкните на кнопке Ping в нижнем правом углу 
экрана.. При этом будет сделана попытка открыть и закрыть только что 
настроенное подключение к серверу. Если параметры клиента указаны корректно, 
то попытка должна завершиться удачно. 
    9.    Нажмите <Ctrl+S> для сохранения информации о подключении и завершите 
работу программы SQLEDIT. 

    На заметку 
    Все приведенные инструкции по настройке соединения остаются в силе и для 
настройки, осуществляемой непосредственно в процессе установки пакета Net Library.	l? 

    SYBPING 

    Для проверки связи с сервером можно использовать утилиту Sybase SYBPING, 
которая находится в папке SYBASE. Для этого достаточно щелкнуть на имени 
нужного сервера в списке этой программы и на кнопке Ping. Если сервер доступен 
для запросов по сети — значит все в порядке. 

    372 Часть III. Справочные материалы 

    Драйверы Windows 3.x 

    Если вам все еще необходима поддержка 16-разрядных клиентных приложений 
(Windows 3.x), то изучите приведенные ниже советы, которые помогут решить 
возникающие проблемы. 
    Q  Все версии Sybase SQL Server, выпущенные раньше, чем System 10, 
используют для организации соединения между клиентом и сервером драйверы 
Sybase DB-Library. System 10 и более новые версии используют драйверы 
CT-Library. Хотя к серверам версии System 10 клиентные приложения Windows 3.x 
также могут подключаться с помощью драйверов DB-Library, но в результате 
окажутся недоступными некоторые специфические для System 10 возможности. В то 
время как Delphi 1.0 использует драйверы DB-Library, Delphi 2.0 и более новые 
версии — как DB-Library, так и CT-Library. Перед настройкой параметров клиента 
проверьте, какие именно драйверы используются. 
    Q   Различные версии драйверов DB-Library не равноценны: некоторые из них 
работают лучше других. У автора лучше всего работают драйверы, датированные 
3-1-94 (1 марта 1994 г.), но это не обязательно будет справедливо повсеместно. 
Верным признаком того, что необходимо проверить драйверы, являются проблемы с 
преобразованием данных. Например, у автора при совместном использовании Delphi 
1.0 и библиотеки драйверов DB-Library, датированной июнем 1994 г., 
преобразование текстовой строки в поле типа даты-времени происходило так, что 
время записывалось в поле два раза вместо одного. Если при использовании 
клиентного приложения Windows 3.x для связи с сервером Sybase происходят 
подобные странности в преобразовании данных, то необходимо испробовать другую 
версию DB-Library. 
    Q   Версии SQL Server, выпущенные раньше, чем System 10, используют другой 
метод отмены запросов и сброса его невостребованных результатов, чем те, 
которые созданы позднее. Для этого используется поддержка стандарта 
Out-Of-Band-Data (OOBD). Соответствующие средства встроены в протокол IPX, но 
для протокола TCP/IP необходимо проверить наличие соответствующего пакета 
обслуживания соединений. Только самые последние версии протокола Workplace 
TCP/IP для локальных сетей Novell имеют встроенную поддержку стандарта OOBD, а 
для предыдущих — необходимы дополнительные средства. 
    Q  Для отмены запросов клиентных приложений Windows 3.x с помощью OOBD 
используется параметр подключения URGENT. Этот параметр просто добавляется в 
конец строки параметров. 
    100.10.15.1,3000,URGENT 
    В результате запросы, отменяемые с помощью функции dbcancel () библиотеки 
DB-Library, возвращают управление в приложение так быстро, насколько это возможно. 
    Q  Для предупреждения и выявления ошибок в подключениях 16-разрядных 
приложений необходимо использовать программу WSYBPING, а не SYBPING, поскольку 
последняя работает только для 32-разрядных клиентов. 
    Q Для работы версий DB-Library для Windows 3.x небходим расширенный 
(enhanced) режим работы процессора 386, хотя при попытке их использования это 
явно не сообщается. Если попытаться подключить клиентного приложения Windows 
3.x к серверу Sybase SQL с помощью драйверов DB-Library в стандартном режиме 
процессора, то подключение не удастся, однако при этом драйверы DB-Library не 
выдадут никакого сообщения о необходимости переключения режима. 

    Настройка псевдонима ВDЕ 

    Как только связь с сервером ба*зы данных установлена, наступает очередь 
создания псевдонима BDE для того, чтобы приложение Delphi могло обращаться к 
серверу. Эта тема освещается в данной книге в другом месте, однако здесь 
приводится ее краткий обзор — для удобства и для раскрытия взаимосвязи между 
настройкой драйверов баз данных и настройкой псевдонимов BDE. 
    Псевдонимы BDE создаются либо с помощью утилиты BDE Administrator, либо с 
помощью приложения Delphi Database Explorer. Приведенные ниже инструкции 
относятся к программе BDE Administrator. 
    1.   Запустите утилиту BDE Administrator, щелкните правой кнопкой на 
вкладке Databases и выберите из меню пункт New. После появления диалогового 
окна New Database Alias выберите в списке Database Driver Name пункт Sybase и 
щелкните на кнопке ОК. 
    2.    После добавления нового псевдонима введите для него имя. 
    3.    Настройте параметры нового псевдонима на странице Definition. 

    Глава 18. Sybase SQL Server	373 

    4.    Щелкните на параметре SERVER NAME и установите его значение равным 
имени вашего сервера SQL Это должно быть то же самое имя, которое 
использовалось в утилите SQLEDIT. 
    5.    По желанию можно указать в параметре USER NAME имя пользователя 
сервера, автоматически регистрируемого в системе по умолчанию. Введенное имя 
будет отображаться по умолчанию при каждом появлении встроенного диалогового 
окна регистрации Delphi. 
    Для сохранения изменений и выхода из программы BDE Administrator щелкните 
на кнопке Apply. 

    Специальные параметры псевдонима BDE 

    Ниже перечислены некоторые параметры псевдонима BDE, которые могут 
оказаться полезными при подключении к серверу Sybase SQL. Хотя для начала 
можно принять значения этих параметров, предложенные по умолчанию, полезно 
знать, какие возможны варианты (особенно при отладке и выявлении ошибок). 
Обратите внимание, что некоторые из этих параметров соответствуют уровню 
драйверов. Доступ к параметрам этого уровня осуществляется через вкладку 
Configuration программы BDE Administrator. 

    APPLICATION NAME 

    В качестве значения параметра APPLICATION NAME можно указать имя процесса, 
которое будет использовано в таблицах системных процессов SQL. Таким образом 
можно отличить свой процесс от других. 

    CONNECT TIMEOUT 

    Этот параметр предназначен для выбора интервала времени, в течение 
которого клиент может осуществлять попытки подключения к серверу SQL. По 
умолчанию значение этого параметра равно 60 с. Увеличение этого значения может 
привести к повышению вероятности подключения рабочих станций-клиентов 
(особенно тех, которые разбросаны по глобальным сетям). 

    HOST NAME 

    Значение этого параметра — имя рабочей станции, которое появляется в 
таблице системных процессов Sybase SQL Server. Благодаря этому можно отличить 
подключения одно от другого, например, в листингах, генерируемых хранимой 
процедурой sp__who. 

    NATIONAL LANG NAME 

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

    TDS PACKET SIZE 

    Этот параметр используется для выбора размера пакетов Tabular Data Stream 
(TDS). TDS — это пакетный протокол высокого уровня, который используется в SQL 
Server для обмена данными с клиентами. Хотя в программе BDE Administrator 
можно указать любой размер пакета от 0 до 65535 байт, в SQL Server не 
поддерживаются пакеты размером менее 512 байт. Может оказаться, что увеличение 
размера пакета приводит к повышению общей пропускной способности системы 
вследствии снижения количества пакетов, необходимого для передачи больших 
объемов дацных (например, полей BLOB). По умолчанию размер пакета установлен 
равным 512 байт; для оптимальной производительности рекомендуется выбирать 
размер между 512 и 8192. 

    На заметку 
    При увеличении максимального размера сетевого пакета необходимо также 
увеличить значение параметра additional network memory. Он используется для 
распределения памяти под внутренние буферы SQL Server, предназначенные для 
обслуживания соединений с клиентами. Если не увеличить параметр 
    additional network memory пропорционально увеличению параметра network 
packet size, то нельзя будет использовать пакеты размером больше 512 байт. 

    374	Часть III. Справочные материалы 

    Для определения максимального размера пакета, поддерживаемого сервером, 
можно использовать хранимую процедуру SQL Server sp_configure. Для отображения 
списка размеров сетевых пакетов введите команду sp_configure 'network packet 
size'. Необходимо установить значение этого параметра, прежде чем изменять 
соответствующий параметр в программе BDE Administrator. Если значения 
параметра IDS PACKET SIZE в программе BDE Administrator и параметра network 
packet size в SQL Server не согласованы (или если значение параметра 
additional network memory выбрано некорректно), то могут возникнуть следующие ошибки. 
    Q	Error:   unknown  user  name   or  password 
    Q	Server error — 4002  Login  failed 
    Q	Server  error — 20014   Login  incorrect 

    DATABASE NAME 

    Этот параметр используется для указания имени базы данных SQL, подключение 
к которой необходимо осуществить. При создании псевдонимов SQL Server обычной 
практикой является выбор отдельного псевдонима для каждой отдельной базы данных. 

    BLOB EDIT LOGGING 

    Установив значение этого параметра равным false, можно отключить контроль 
изменений в полях BLOB. Использование данного значения минимизирует 
потребность в ресурсах памяти и дискового про-страйства, а также улучшает 
производительность системы. Объекты BLOB будут передаваться с использованием 
утилиты bulk copy, так что необходимо будет включить режим select into/bulk 
copy в базе данных назначения, например, с помощью хранимой процедуры sp_dboption. 

    MAX QUERY TIME 

    Этот параметр задает интервал времени, в течение которого программа SQL 
Links ждет завершения асинхронного запроса, прежде чем отменить его. Для 
драйверов Sybase SQL Links в настоящее время по умолчанию предусмотрен 
синхронный режим выполнения запроса. Асинхронное выполнение запросов 
включается путем увеличения значения параметра DRIVER FLAG на 2048. Для выбора 
времени ожидания по синхронному запросу используется параметр TIMEOUT. По 
умолчанию драйверы SQL Links предоставляют запросу для его завершения пять 
минут (300 с). 

    Некоторые замечания о Sybase SQL Server 

    Помимо настройки псевдонима, при разработке приложений Delphi для 
обращения к базам данных Sybase необходимо учитывать еще целый ряд важных 
моментов. Некоторые из возникающих вопросов освещены ниже. 

    Типы данных Numeric И Decimal 

    В версии Sybase System 10 введены новые типы данных: Numeric и Decimal. 
Эти типы обрабатываются в BDE путем преобразования в числовые значения с 
плавающей точкой, f idFloat. Однако следует заметить, что данные обоих типов 
загружаются с сервера в их исходных форматах (xltNone), так что никакой потери 
данных при преобразовании не происходит. 

    Полные имена таблиц базы данных и объектов сервера 

    К объектам Sybase других баз дашгых необходимо обращаться по полным 
именам. Так, для открытия таблицы CUSTOMER, принадлежащей пользователю DEMO, 
из базы данных ACCOUNTING, используется имя 

    ACCOUNTING.DEMO.CUSTOMER. %  , 


    Устранение проблем при подключении к серверу Sybase 

    Если у вас возникли проблемы с подключением к Sybase SQL Server, 
попробуйте проделать следующее. 
    1.    Используйте для подключения к серверу утилиту Sybase SYBPING. Если с 
помощью этой утилиты связь с сервером устанавливается, то, вероятно, имеется 
ошибка в конфигурации псевдонима BDE. Вернитесь к программе BDE Administrator 
и проверьте значения параметров (в частности, имя сервера). 

    Глава 18. Sybase SQL Server	375 

    2.    Если с помощью утилиты SYBPING соединение установить нельзя, то 
возможна проблема с протоколом. Если для подключения к серверу используется 
протокол TCP/IP, то попытайтесь вызвать главный компьютер через утилиту PING, 
поставляемую вместе с системами Windows 95 и Windows NT. Для вызова 
используйте как имя компьютера, указанное в файле HOSTS, так и его IP-адрес.	, 

    На заметку 
    Не перепутайте утилиту SYBPING с утилитой WSYBPING. Последняя 
предназначена только для 16-разрядных клиентов и не будет работать для 
32-разрядных приложений. 

    3.    Если обращение к компьютеру через утилиту PING по IP-адресу 
происходит корректно, а по имени — нет, то проблема, вероятно, связана с 
файлом HOSTS. Временное решение этой проблемы — изменить строку параметров 
подключения (с помощью программы SYBEDIT) так, чтобы вместо имени 
использовался IP-адрес. Проблему с файлом HOSTS необходимо решить как можно 
быстрее, поскольку подключение к удаленным компьютерам по имени является более 
гибким и удобным способом. 
    4.    Если для подключения к серверу используется протокол IPX, то 
проверьте совпадение сетевого IPX-номера сервера Novell с тем, который указан 
в программе SYBEDIT. Если номера совпадают, а связи все равно нет, или если 
используется другой протокол, то проконсультируйтесь с администратором сети. 
    5.    Если используется протокол TCP/IP и вызов через PING как по имени, 
так и по IP-адресу не происходит, то, по всей видимости, имеется неполадка в 
сети. Проверьте такие очевидные вещи, как правильность IP-адреса сервера. 
Попробуйте обратиться по фиктивному зацикливающему адресу TCP/IP, 127.0.0.1, 
чтобы проверить правильность работы стека TCP/IP. Этот адрес предназначен для 
эмуляции вызова компьютера из сети. Если такой вызов не срабатывает, то в 
конфигурации протокола имеются серьезные ошибки. Для их устранения необходимо 
проконсультироваться с администратором сети. 
    6.    Если соединение через SYBPING не срабатывает, но вызов через PING 
происходит корректно, то проверьте, является ли порт, указанный в строке 
параметров подключения, портом ввода сервера базы данных. Для определения 
необходимого номера порта следует обратиться к администратору базы данных. 
Порты ввода настраиваются в версии System 10 с использованием утилиты Sybase SYBINIT. 
    7.    Если в конфигурации параметров на первый взгляд нет ошибок, то можно 
попробовать сменить протокол (в том случае, если имеется выбор). Автору 
встречались, например, случаи, когда версия System 10 для Novell NetWare не 
работала с собственным протоколом Novell IPX, но работала с протоколом TCP/IP. 
Поскольку сервер можно настроить на прием сообщений сразу по нескольким 
протоколам, его можно временно использовать с работающим протоколом, пока не 
будет обнаружена причина неполадок. 

    Азы SQL 

    В этом разделе дается введение в диалект Transact-SQL для Sybase SQL 
Server и затрагиваются некоторые возможности и особенности, которые отличают 
его от реализаций SQL других производителей. Предполагается, что ваш сервер 
находится в активном состоянии, и вы знаете, как подключиться к нему с помощью 
утилиты SQL Server I SQL. 

    Создание базы данных 

    У вас уже, наверное, есть база данных, содержащая несколько временных 
таблиц для работы с примерами данной главы. Если нет, то такую базу данных 
нетрудно создать. В SQL база данных создается командой CREATE DATABASE. Т$уный 
синтаксис команды зависит от реализации конкретной СУБД. Вот базовый синтаксис 
Transact-SQL: *%

    CREATE   DATABASE  имяБД  ON  устройство_данных=.р<эзл/ер LOG  ON  устройство_регистрации=разл?ер 

    Прежде чем создавать базу данных, необходимо узнать, на каких логических 
устройствах (logical device) ее можно размещать. С помощью логических 
устройств SQL Server при создании базы данных можно избежать обращения к 
областям физических дисков. 
    Для создания устройств SQL Server используется команда DISK INIT. Вот 
пример ее применения: 

    376	Часть III. Справочные материалы 

    DISK INIT 
    name='saldatOO', 
    physname='c:\sybasesql\data\saldatOO.dat', 
    vdevno=5, 
    size=2048 

    В параметре name указывается логическое имя устройства. 

    Параметр physname используется для подробного описания местонахождения и 
имени файла устройства. Это может быть файл файловой системы или логический диск. 
    Параметр vdevno содержит номер логического виртуального устройства. 
Единственное требование, предъявляемое к нему — это уникальность номера для 
каждого отдельного устройства, существующего на сервере. Диапазон допустимых 
значений — от 1 до 255. Значение 0 зарезервировано для основного устройства. 
Чтобы использовать номера больше 10, необходимо увеличить максимальное 
разрешенное количество устройств с помощью хранимой процедуры sp_conf igure. 
    Параметр size содержит количество двухкилобайтных страниц, занимаемых 
устройством. Например, если создается устройство емкостью 4 Мбайт (4096 
Кбайт), то следует указать значение 2048. 
    Устройства данных и регистрации создаются одинаковыми командами. Вот 
пример команды создания устройства регистрации SQL Server: 

    DISK INIT 
    name='sallogOO', 
    physname='с:\sybasesql\data\sallogOO.dat', 
    vdevno=6, 
    size=512 

    Как только созданы устройства, можно создавать саму базу данных, которая 
будет на них храниться. Вот пример команды CREATE DATABASE, использующей 
только что созданные устройства: 

    CREATE   DATABASE   sales   ON   saldatOO=4   LOG  ON   sallogOO=l 

    Если у вас до сих пор не было базы данных для проработки примеров этого 
раздела, то не мешкайте — создайте ее прямо сейчас. 

    Команда USE 

    Команда USE изменяет контекст активной базы данных, или, проще говоря, она 
переключает текущую базу данных. Команда имеет следующий синтаксис: 

    USE  имяБД 


    Создание таблиц 

    После создания базы данных и выполнения команды USE для ее активизации 
можно приступать к созданию объектов базы данных. Практически все основные 
понятия реляционных баз данных можно продемонстрировать на примере набора из 
трех таблиц. Для работы с примерами этой главы начните с создания трех таблиц, 
приведенных ниже. Таблицы создаются оператором SQL CREATE TABLE. Для создания 
таблицы CUSTOMER введите с помощью^ утилиты ISQL следующую команду. 

    CREATE TABLE CUSTOMER 
    CustomerNumber	int4	NOT NULL, 
    LastName	char (30)	NULL, 
    FirstName	char^SO)	NULL, 
    StreetAddress	char (30)	NULL, 
    City	char(20)	NULL, 
    State	ЧЙцг(2)	NULL, 
    Zip	chSir(lO)	NULL ) 

    Затем с помощью следующей команды создайте таблицу SALE. 

    CREATE TABLE SALE ( 
    SaleNumber      int      NOT NULL, SaleDate        datetime  NULL, 

    Глава 18. Sybase SQL Server	377 

    CustomerNumber       int	NOT  NULL, ItemNumber                 int         
        NOT  NULL, Amount                           money ) 

    Итак, таблица SALE создана. Осталась всего одна таблица — ITEM, и она 
создается следующей командой. 

    CREATE TABLE ITEM 
    ( 
    ItemNumber    int      NOT NULL, 
    Description   char(30)  NULL, 
    Price        money    NULL 


    Добавление и удаление столбцов 

    Для добавления столбцов в существующую таблицу используется команда SQL 
ALTER TABLE. Вот пример добавления столбца в таблицу: 

    ALTER   TABLE   CONTACT 
    ADD  PhoneNumber  char(10)   NULL 

    Столбец удаляется из таблицы следующим образом: 

    ALTER TABLE CONTACT DROP PhoneNumber 

    Обратите внимание, что нельзя добавить столбец со значением NOT NULL в 
таблицу, в которой уже есть строки, поскольку сразу же после добавления в 
таблицу элементам столбца автоматически присваивается значение NULL. 

    Предупреждение 

    В документации по Sybase SQL Server ничего не сказано о синтаксической 
конструкции ALTER TABLE .... DROP столбец. Так как это недокументированная 
возможность, ее следует использовать при разработке приложений с осторожностью. 

    Ограничения 

    Ограничением (constraint) называется механизм определения допустимых типов 
данных данного столбца. С помощью ограничений можно задавать значения для 
полей по умолчанию. Ограничения могут задаваться непосредственно при создании 
таблицы с помощью команды CREATE TABLE или впоследствии, с помощью команды 
ALTER TABLE. Вот пример офаничения первичного ключа: 

    ALTER  TABLE   CUSTOMER 
    ADD  PRIMARY KEY   (CustomerNumber) 

    Приведенная команда добавляет в таблицу CUSTOMER ограничение первичного 
ключа, назначая первичным ключом таблицы поле^Сиз^тегЫшпЬег. В результате для 
таблицы создается уникальный индекс, использующий в качестве ключа столбец 
CustomerNumber. Обратите внимание, что в качестве первичного ключа нельзя 
использовать столбец, допускающий использование значения NULL. 
    Ограничение внешнего ключа Определяет столбец одной таблицы, значения 
которого должны существовать во второй таблице, называемой внешней. В отличие 
от первичного ключа, внешний ключ не является уникальным индексом строки. 
Наобврот, ключевые столбцы должны быть первичными (уникальными) ключами во 
внешней таблице. При добавлении ограничения внешнего ключа в таблицу SQL 
Server автоматически строит вторичный ключ по^ключевым полям. Вот пример 
соответствующей команды: 

    ALTER  TABLE   SALE	*^ 
    ADD  FOREIGN  KEY   (CustomerNumber)   REFERENCES   CUSTOMER 

    Эта ограничение назначает поле CustomerNumber таблицы SALE внешним ключом, 
который ссылается на аналогичное поле таблицы CUSTOMER. Это означает, что 
введенные в таблицу SALE номера покупателей должны существовать в таблице 
CUSTOMER, а также то, что номера, использующиеся в таблице SALE, нельзя 
удалить из таблицы CUSTOMER. Такая возможность обеспечения наличия связи между 
двумя таблицами путем ее изначального определения называется декларативной 
ссылочной целостностью (declarative referential 

    378	Часть III. Справочные материалы 

    integrity). Этот термин означает, что обеспечение целостности ссылок 
таблиц друг на друга выполняется при их создании или объявлении на уровне 
сервера базы данных, а не на уровне приложения. 
    Третьим типом ограничения является сравнение значений столбца со списком 
предварительно определенных значений. Вот пример задания такого ограничения: 

    ALTER TABLE CUSTOMER 
    ADD CONSTRAINT INVALID_STATE CHECK (State in СОК', 'AR', 'MO')) 

    Обратите внимание на негативный смысл имени, выбранного для ограничения. 
Это делается для того, чтобы при выдаче сообщения о нарушении установленного 
ограничения пользователь мог бы определить источник проблемы по одному лишь 
имени ограничения. Кроме того, таким образом можно сэкономить усилия при 
замене обработчика исключительной ситуации, генерируемой Delphi по умолчанию, 
на созданный вами. 

    Тестирование ограничения 

    Необходимо тестировать каждое ограничение, налагаемое на таблицу. Чтобы 
проделать это, попытайтесь внести в базу данных значение, которое запрещено 
наложенным ограничением. Например, для тестирования описанного выше 
ограничения INVALID_STATE введите с помощью утилиты ISQL следующую команду. 

    INSERT   INTO  CUSTOMER   (CustomerNumber,   State) VALUES    (123,'CA') 

    Поскольку ранее наложенное ограничение устанавливает, что в качестве 
названия кода штата должны использоваться только значения ' ок', ' AR ' и ' 
МО', попытка ввести новую строку должна закончиться сообщением об ошибке. 
    Если заданное ограничение не функционирует как положено, то проверьте, 
правильно ли оно добавлена и корректно ли оно выполняет проверку данных. 

    Создание индексов 

    Индексы в SQL Server создаются командой CREATE  INDEX. Вот ее базовый синтаксис: 

    CREATE   INDEX   SALE02   ON  SALE    (SaleDate) 

    Здесь SALE02 — имя нового индекса, SALE — имя таблицы, по которой строится 
индекс, a SaleDate — ключ индекса. Обратите внимание, что имена индексов SQL 
Server должны быть уникальны по всей базе данных, в которой они располагаются. 
    С помощью варианта данной команды CREATE UNIQUE INDEX создается индекс, не 
допускающий повторений. 

    CREATE UNIQUE INDEX SALE01 ON SALE (SaleNumber) 


    Вставка данных 

    Оператор SQL INSERT используется для добавления данных в таблицу на 
сервере SQL. С помощью ключевого слова VALUES оператора INSERT можно вставить 
одну строку; если же выбрать несколько строк из другой таблицы, то можно 
вставить все эти строки одновременно. Для добавления данных в каждую из трех 
таблиц используются команды, приведенные ниже. Вначале вставляются три строки 
в таблицу CUSTOMER. 

    INSERT   INTO  CUSTOMER   (CustomerNumber,   LastName, FirstName,   
StreetAddress,   City,   State,   Zip) VALUES(1,'Doe','John',423   
SunnyLane','Anywhere', 'MO','73115') 
    INSERT   INTO  CUSTOMER   (CustomerNiimber,   LastName, FirstName,   
StreetAddress,   City,   State,   Zip) VALUES(2,'Doe','Jane','123   
SunnyLane','Anywhere', 'MO' , '73115' )	>%,,,. 
    INSERT   INTO  CUSTOMER   (CustomerNumber,    LastName, FirstName,   
StreetAddress,   City,   State,   Zip) VALUES(3,'Philgates','Buck','57   
Riverside','Reo', 'AR','65803') 

    После этого добавляются три строки в таблицу ITEM. 

    INSERT   INTO   ITEM   (ItemNumber,   Description,   Price) VALUES(1001, 
'Zoso  LP',13.45) 

    Глава 18. Sybase SQL Server	379 

    INSERT INTO ITEM (ItemNumber, Description, Price) VALUES(1002,'White LP',67.90) 
    INSERT INTO ITEM (ItemNumber, Description, Price) VALUES(1003, 'Bad Co. LP',11.45) 
    Наконец, добавляются четыре строки в таблицу SALE. 
    INSERT INTO SALE (SaleNumber, SaleDate, CustomerNumber, 
    ItemNumber, Amount) 
    VALUES(101, 40/18/90',1,1001,13.45) 
    INSERT INTO SALE (SaleNumber, SaleDate, CustomerNumber, 
    ItemNumber, Amount) 
    VALUES(102, '02/27/92',2,1002,67.90) 
    INSERT INTO SALE (SaleNumber, SaleDate, CustomerNumber, 
    ItemNumber, Amount) 
    VALUES(103,'05/20/95',3,1003,11.45) ' 
    INSERT INTO SALE (SaleNumber, SaleDate, CustomerNumber, 
    ItemNumber, Amount) 
    VALUES(104, '11/27/97',1,1002,67.90) 

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

    INSERT INTO ITEM (Price, ItemNumber) VALUES(13.45,1001) 


    Команда UPDATE 

    Команда SQL UPDATE используется для изменения данных, которые уже 
находятся в таблице. Оператор UPDATE может содержать ключевое слово WHERE, 
который определяет, какие именно строки следует модифицировать. Вот синтаксис 
этой команды: 

    UPDATE CUSTOMER SET Zip='65803' WHERE City='SpringField' 

    Наличие ключевого слова WHERE в операторе UPDATE может привести к тому, 
что в таблице будет изменена, например, всего одна строка; в этом случае для 
изменения всех строк таблицы достаточно убрать ключевое слово WHERE. 

    UPDATE CUSTOMER SET State='MO' 

    Столбец можно также модифицировать, использовав значения других столбцов 
таблицы или даже его собственные значения. Например, необходимо увеличить цену 
каждого наименования товара в таблице ITEM на семь процентов. Для этого 
команда UPDATE используется следующим образом. 

    UPDATE ITEM 
    SET Price=Price+ (Price* .""67) 


    Команда DELETE' 

    Для удаления строк из таблицы используется команда DELETE. Чтобы удалить 
все строки, используйте следующий синтаксис: 

    DELETE FROM CUSTOMER  %.. 
    11'"u,: 

    Команда DELETE может содержать ключевое слово WHERE для отбора отдельных строк. 

    DELETE FROM CUSTOMER WHERE LastNameO'Doe' 

    380	Часть III. Справочные материалы 

    Управление транзакциями 

    Транзакцией (transaction) называется группа изменений в базе данных. 
Пользовательские транзакции инициируются с помощью команды BEGIN TRANSACTION. 
Все внесенные в ходе транзакции изменения заносятся в базу данных с помощью 
команды COMMIT, а отменяются командой ROLLBACK. Обе последние команды 
применимы только к изменениям, внесенным в базу данных после последней команды 
COMMIT; все сделанные до этого изменения отменить нельзя. 

    На заметку 
    Наряду с обычными операторами языка управления данными DML (Data 
Manipulation Language), например, INSERT, UPDATE и DELETE, в пользовательские 
транзакции можно включать также операторы языка определения данных DDL (Data 
Definition Language). Если отменить транзакцию, в ходе которой создается 
объект, то объект уничтожается. Это свойство можно использовать для сохранения 
или сброса содержимого рабочей таблицы, в зависимости от успешности вставки в 
нее каких-либо данных. Так, если в одну транзакцию включены операторы CREATE 
TABLE и INSERT, то при неудачном выполнении оператора INSERT таблица 
автоматически уничтожается. 

    Команда SELECT 

    По команде SQL SELECT отображается содержимое таблицы. Для примера давайте 
проверим содержимое трех таблиц, созданных в данной главе, с помощью этой 
команды. Введите для каждой таблицы команду SELECT * FROM имя_таблицы, заменив 
имя_таблицы на фактическое имя (т.е. на CUSTOMER, SALE или ITEM). К настоящему 
моменту в каждой из трех таблиц должно быть по крайней мере по три строки. 
Проверьте это с помощью оператора SELECT. 
    По команде SELECT * выводятся все столбцы всех строк таблицы. Чтобы 
выбрать отдельные поля, замените звездочку на список полей, отделенных друг от 
друга запятыми. 
    SELECT   CustomerNumber,   LastName,   State   FROM  CUSTOMER 


    Выражения в столбцах 

    Каждый пункт в списке полей оператора SELECT может представлять собой не 
просто название столбца, но выражение (expression column), включающее 
арифметические операции, константы и функции. Вот пример оператора SELECT, 
который возвращает записи из таблицы SALE с торговой наценкой $15: 

    SELECT   SaleNumber,SaleDate,   AmountPlusShipping=Amount+15 FROM  SALE 


    Вычисляемые столбцы 

    Вычисляемые столбцы (aggregate column) — функции, применяемые для 
выполнения каких-то вычислений над некоторым набором данных. В качестве таких 
функций могут служить COUNT, SUM, AVG, MIN и MAX. Вот некоторые примеры их 
использования. Следующий запрос подсчитывает количество покупателей, внесенных 
в таблицу. 

    SELECT   COUNT(*)    FROM  CUSTOMER 

    По данному запросу выводится ёумма максимальной продажи. SELECT  
MAX(Amount)    FROM  SALE 
    А следующий запрос возвращает о%щую сумму всех продаж. 

    SELECT SUM(Amount) FROM SALE 


    Ключевое слово WHERE ^ 

    Ключевое слово SQL WHERE используется для задания дополнительных условий 
на данные, выбираемые оператором SELECT. Вот некоторые примеры. Этот оператор 
возвращает список клиентов, живущих в шт. Миссури (код штата — мо): 

    SELECT * FROM CUSTOMER WHERE State='MO' 

    Глава 18. Sybase SQL Server 381 

    Приведенный ниже запрос возвращает список тех покупателей, у которых в 
поле почтового адреса имеется строка Sunny. 

    SELECT * FROM CUSTOMER 
    WHERE StreetAddress LIKE '%Sunny%' 

    Обратите внимание, что сравнение производится с учетом верхнего и нижнего 
регистра символов. Если в этом нет необходимости, то используйте функцию UPPER 
для преобразования всех символов полей и получаемых значений к верхнему регистру. 
    Следующий оператор возвращает список продаж на сумму более $500. 

    SELECT * FROM SALE WHERE Amount > 500 

    А этот запрос возвращает список только тех продаж, которые осуществлены с 
18 октября 1990 г. по 20 мая 1995 г. включительно. 

    SELECT   *   FROM  SALE 
    WHERE   SaleDate   BETWEEN   40/18/90'   AND   '05/20/95' 


    Объединения 

    Ключевое слово WHERE используется также для объединения (join) таблиц и 
образования составных наборов данных. Присоединение одной таблицы к другой с 
помощью ключевого слова WHERE требует двух изменений в базовом синтаксисе 
команды SELECT. Первое изменение состоит в использовании в операторе SELECT 
ключевого слова FROM, с помощью которого указываются дополнительные таблицы, а 
второе — в применении операции сравнения (=) для создания выражения, которое с 
помощью ключевого слова WHERE определяет поля, используемые для объединения 
указанных таблиц. Вот пример: 

    SELECT  CUSTOMER. Customer_Number,    SALE. Amount 
    FROM  CUSTOMER,    SALE 
    WHERE  CUSTOMER.CustomerNumber=SALE.CustomerNumber 

    Обратите внимание на то, что в список, определяемый с помощью ключевого 
слова FROM, включена таблица SALE, а также на то, что для объединения таблиц 
CUSTOMER и SALE используется знак равенства между их полями CustomerNumber. 
Таблица, расположенная слева от знака равенства, называется внешней (outer), а 
справа — внутренней (inner). Их также называют соответственно левой (left) и 
правой (right) таблицами, что указывает на их взаимное расположение в 
левостороннем объединении (left join) — наиболее распространенном типе 
объединений в запросах SQL. 

    Различие между внутренними и внешними объединениями 

    Упомянутые в предыдущем разделе левые объединения известны также под 
формальным названием внутренних объединений (inner join). Внутренние 
объединения возвращают строки таблицы только в том случае, если выполняется 
условие объединения. В противоположность этому, во внешнем объединении (outer 
join) строки возвращаются независимо от выполнения условия, однако если 
условие не выполняется, то в качестве значений полей внутренней таблицы в 
выходной набор данных помещаются значения NULL. Вот пример внешнего 
объединения в языке Transact-SQL: 

    SELECT  CUSTOMER.CustomerNumber,   SALE.Amount 
    FROM  CUSTOMER,    SALE 
    WHERE   CUSTOMER.CustomerNumber*=SALE.CustomerNumber 


    ANSI-синтаксис объединений 

    Помимо собственного синтаксиса, для построения объединений СУБД Sybase SQL 
Server поддерживает ANSI-синтаксис. Для левого внутреннего объединения он 
выглядит следующим образом. 

    SELECT  CUSTOMER.CustomerNumber,   SALE.Amount 
    FROM  CUSTOMER  LEFT   JOIN   S^tbit 
    ON  CUSTOMER.CustomerNumber=SALE.CustomerNumber 
    Для левого внешнего объединения используется следующий синтаксис. 
    SELECT CUSTOMER.CustomerNumber, SALE.Amount 
    FROM CUSTOMER LEFT OUTER JOIN SALE 
    ON CUSTOMER.CustomerNumber=SALE.CustomerNumber 

    382	Часть III. Справочные материалы 

    Для создания правых внешних объединений достаточно заменить LEFT на RIGHT. 
Обратите внимание, что правые и левые внутренние объединения — это фактически 
одно и то же, и между ними нет никаких синтаксических различий. 

    Многоуровневые объединения 

    Многоуровневым объединением (multi-tier join) называется объединение, 
включающее более двух таблиц. С помощью таких объединений таблица А 
присоединяется к таблице Б, которая в свою очередь присоединяется к таблице в. 
Рассмотрим следующий запрос. 

    SELECT  C.LastName,С.FirstName,I.Description,S.Amount 
    FROM  CUSTOMER  C, 
    SALE   S, 
    ITEM  I 
    WHERE С.CustomerNumber=S.CustomerNumber 
    AND S.ItemNumber=I.ItemNumber 

    В данном запросе таблицы CUSTOMER и SALE объединяются по общему ключу — 
полю CustomerNumber. После этого по общему ключу, полю ItemNumber, 
объединяются таблицы SALE и ITEM. В результате все три таблицы объединяются в 
один общий набор данных. 

    Самообъединения 

    Помимо объединения с другими таблицами, любая таблица может быть 
объединена сама с собой. Этот тип объединений называется рефлексивным 
(reflexive join) или самообъединением (self-join). Рассмотрим следующий запрос. 

    SELECT   S.CustomerNumber,   S.Amount, 
    (S.Amount   /   SUM(S2.Amount))*100   Percentage FROM  SALE   S, SALE   S2 
    WHERE   S.CustomerNumber=S2.CustomerNumber GROUP BY  S.CustomerNumber,   S.Amount 

    Целью этого запроса является получение информации о продажах каждому 
отдельному покупателю, со сравнением объема каждой продажи и общего объема 
продаж данному клиенту. Единственным способом проделать все это в одном 
операторе SELECT является использование самообъединений. Данные собираются и 
группируются по покупателям, а затем таблица SALE присоединяется сама к себе 
для выяснения общего объема продаж каждому покупателю. После этого объем 
текущей продажи делится на общий объем и преобразуется к процентному значению. 

    Тета-объединения 

    В тета-объединениях (theta join) две таблицы объединяются с использованием 
операций сравнения, отличных от проверки на равенство.. Обычно в таких 
объединениях используется операция проверки неравенства (<>). Ниже приводится 
пример тета-объединения; это разновидность запроса, использованного выше для 
демонстрации самообъединений. 

    SELECT  С.CustomerNumber,S.Amount,SUM(S2.Amount)   OTHERS 
    FROM  CUSTOMER  C, 
    SALE   S, 
    SALE   S2 
    WHERE С. CustomerNumber=S . Custome*rNumber 
    AND C.CustomerNumber<>S2.CustomerNumber 
    GROUP BY C.CustomerNumber, S.Amount 

    Фактически данный запрос содержит два объединения. Во-первых, для 
получения всех продаж по каждому покупателю объединяются таблицы CUSTOMER и 
SALE. Во-вторых, используется тета-объединение для получения всех продаж, 
которые не связаны с данным покупателем. Поскольку для обращения к одной и той 
же таблице SALE используются два разных типа объединений, для нее введены два 
разных псевдонима. 

    Полные объединения 

    В полном объединении (full join) комбинированные строки двух таблиц 
обрабатываются без использования условий, задаваемых с помощью ключевого слова 
WHERE. Это объединение применяется для получения данных из таблиц с нестрогими 
связями. Если ни одна из таблиц не обязана содержать нужные вам стро

    Глава 18. Sybase SQL Server	383 

    ки, то можно объединить их во внешнее объединение для получения всех 
строк. Вот пример такого объединения: 

    SELECT   ITEM.Description,   ITEM.Price,   SALE.Amount 
    FROM  SALE   FULL  OUTER   JOIN   ITEM 
    ON  ITEM.ItemNumber=SALE.ItemNumber 

    Декартово произведения 

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

    SELECT   SALE.SaleNumber,    ITEM.ItemNumber 
    FROM  SALE,    ITEM 
    ORDER BY  SaleNumber,   ItemNumber 

    Получение декартового произведения для больших таблиц может надолго 
загрузить сервер. Так надолго, что иногда приходится отменять запрос или 
отключаться от сервера. Поэтому декартовых произведений следует по возможности 
избегать, особенно в больших таблицах. 

    Вложенные запросы 

    Вложенным запросом (subquery) называется оператор SELECT, указанный после 
ключевого слова WHERE другого оператора SELECT. Обычно вложенные запросы 
используются для получения списка данных, по которому затем производится новый 
поиск в таблице. 

    SELECT   *   FROM  CUSTOMER 
    WHERE  CustomerNumber   IN(SELECT  CustomerNumber   FROM  SALE) 

    Некоторые операторы, такие как ANY, ALL, SOME, EXISTS и SINGULAR, работают 
исключительно во вложенных запросах. Хотя ключевое слово ALL используется 
также в операторе SELECT, как отдельный оператор оно применяется только во 
вложенных запросах. 

    GROUP   BY 

    Поскольку SQL является языком запросов, ориентированным на множества, 
операторы группировки данных встроены непосредственно в язык. Программисты, 
работающие с другими СУБД, нередко находят такой подход необычным ввиду своей 
привычки работать с данными построчно. Построчный перебор таблицы для 
получения некоторой итоговой информации — довольно распространенный способ 
обработки данных в локальных СУБД для персональных компьютеров. К счастью, в 
SQL это не так. Один-единственный оператор SQL может делать то же, что и 10, а 
то и 50, строк кода dBASE. "Виновниками" этого чуда являются ключевое слово 
GROUP BY оператора SELECT и функции вычисляемых столбцов SQL. Вот пример 
использования ключевого слова GROUP BY: 

    SELECT  CUSTOMER.CustomerNumber,   sum(SALE.Amount)   TotalSale 
    FROM  CUSTOMER,    SALE 
    WHERE  CUSTOMER.CustomerNumber=SALE.CustomerNumber 
    GROUP  BY  CUSTOMER.CustomerNumber 

    Этот запрос возвращает список всех покупателей вместе с общим объемом 
продаж по каждому покупателю. 
    Как определить, какие поля включать в список, определяемый с помощью 
ключевого слова GROUP BY? Работая с SQL Server, необходимо группировать строки 
ключевого словом GROUP BY по всем не являющимся вычисляемыми столбцам, 
включенным в список оператора SELECT. Использование ключевого слова GROUP BY 
подразумевает наличие в списке столбцов оператора SELECT хотя бы одного 
составного столбца; SQL Server просто не даст вам вставить ключевое слово 
GROUP BY, если такого столбца не будет. 

    %> 
    HAVING	^ 

    Ключевое слово HAVING оператора SELECT используется для наложения условий 
на строки, возвращаемые при использовании ключевого слова GROUP BY. Результат 
его совместной работы с GROUP BY напоминает результат работы оператора SELECT 
с ключевым словом WHERE, с той разницей, что HAVING выполняет операции WHERE 
над строками возвращаемого набора, а не над строками таблицы. 

    384	Часть III. Справочные материалы 

    Обычно бывает удобнее налагать условия на строки таблицы, чем на строки 
возвращаемого набора. Как правило, использование HAVING менее эффективно, чем 
WHERE, потому что в первом случае строки выбираются после их организации в 
группы, тогда как во втором — до этого. Однако вот один из примеров удачного 
использования ключевого слова HAVING. 

    SELECT  CUSTOMER.LastName,   COUNT(*)   NumberWithName 
    FROM  CUSTOMER 
    GROUP  BY  CUSTOMER.LastName 
    HAVING  COUNT(*)    >   1 

    Наилучшим использованием HAVING является наложение ограничений на строки 
возвращаемого набора данных на основе вычисляемых столбцов. В этом случае 
ключевое слово WHERE просто не срабатывает, поскольку информация, заданная в 
условии, не существует до выполнения запроса и вычисления результатов. 

    ORDER  BY 

    Ключевое слово ORDER BY используется для упорядочения строк в выходном 
наборе данных. Вот пример его использования: 

    SELECT * FROM CUSTOMER ORDER BY STATE 

    Псевдонимы столбцов 

    Вы, должно быть, отметили, что для результатов вычисления функций 
наподобие COUNT () и зим () постоянно использовались имена фиктивных столбцов. 
Такие имена называются псевдонимами столбцов (column alias) и предназначены 
для того, чтобы запросы и результаты их выполнения было легче читать. В 
диалекте Sybase SQL Server языка SQL псевдоним столбца может стоять сразу же 
после имени соответствующего столбца в списке оператора SELECT, или слева от 
него, перед знаком равенства. Например, в следующем запросе для вычисляемого 
столбца, создаваемого функцией COUNT (), используется псевдоним NumberWithName. 

    SELECT   CUSTOMER.LastName,   NumberWithName=COUNT(*) 
    FROM   CUSTOMER 
    GROUP  BY  CUSTOMER.LastName 
    HAVING  COUNT(*)    >   1 

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

    SELECT  CUSTOMER.LastName   LNAME,   COUNT(*)   NumberWithName 
    FROM   CUSTOMER 
    GROUP  BY  CUSTOMER.LastName 

    В возвращаемом наборе этого запроса вместо настоящего имени поля LastName 
подставляется псевдоним LName. Обратите внимание, что псевдонимы нельзя 
применять в других фрагментах запроса, например, в условиях WHERE и GROUP BY 
-^, в них необходимо использовать настоящие имена столбцов. 

    Псевдонимы таблиц 

    Вместо того, чтобы всякий раз в операторе SELECT употреблять полное имя 
таблицы, можно заменить его кратким удобным обозначением по сйоему выбору. Это 
делается путем указания псевдонима таблицы (table alias) в списке таблиц, 
определяемом с помощью ключевого слова FROM оператора SELECT. Псевдоним 
ставится справа от настоящего имейи^аблицы, как показано в следующем примере. 

    SELECT   С.LastName,    COUNT(*)   NumberWithName FROM  CUSTOMER  С GROUP  
BY  C.LastName 

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

    Глава 18. Sybase SQL Server	385 
    13 Delphi 3 и системы клиент/сервер 

    Представления 

    Представление (view) таблицы в SQL создается с помощью оператора SELECT, 
после чего с полученным набором данных можно обращаться как с таблицей, и, в 
свою очередь, применять к нему операторы SELECT. В некоторых случаях к 
представлению можно применять также операторы INSERT, DELETE и UPDATE. В самом 
представлении данные не хранятся — это всего лишь логическая конструкция. 
Представление можно считать маленькой SQL-программой, которая выполняется при 
каждом запросе. При обращении к представлению оптимизатор запросов находит 
оператор SELECT, используемый для создания представления, совмещает его с 
оператором, применяемым к представлению, и оптимизирует оба оператора, 
рассматривая их как один запрос. 
    Представления SQL создаются с помощью команды CREATE VIEW. Вот пример: 

    CREATE VIEW MOCUSTOMERS AS SELECT * FROM CUSTOMER WHERE State='MO' 

    После создания представления к нему можно обращаться с запросами точно так 
же, как к таблице. 

    SELECT * FROM MOCUSTOMERS 

    При выполнении этого запроса обратите внимание, что даже при отсутствии 
ключевого слова WHERE во внешнем операторе SELECT, применяемом к 
представлению, результат выглядит так, будто этот ключевое слово присутствует, 
потому что оно встроено в само представление. 
    Оператор SELECT, который образует представление, может делать практически 
все то же самое, что и обычный оператор SELECT, за одним исключением: он не 
может содержать ключевого слова ORDER BY Это ограничение существует не только 
в Sybase SQL Server, но и в системах InterBase, Microsoft и Oracle. 
    При создании модифицируемого представления можно указать, чтобы сервер 
проверял, удовлетворяют ли модифицируемые или добавляемые в запрос строки 
критериям, указанным в представлении. Другими словами, сервер может следить за 
тем, чтобы модифицированная или добавленная запись не вышла за рамки 
представления и не исчезла из виду. Это делается путем использования ключевого 
выражения WITH CHECK OPTION в команде CREATE VIEW. Вот пример соответствующей команды. 

    CREATE VIEW MOCUSTOMERS AS SELECT * FROM CUSTOMER WHERE State='MO' WITH 
CHECK OPTION 

    После этого будут блокироваться все попытки модифицировать старые или 
ввести новые записи, не содержащие в поле state значение 'МО'. 

    Хранимые процедуры 

    Хранимой процедурой (stored procedure) называется скомпилированная 
программа на языке SQL, которая хранится в базе данных вместе с другими 
объектами. Хранимые процедуры создаются командой CREATE PROCEDURE, пример 
которой приведен ниже. 

    CREATE PROCEDURE listcustomers AS 
    BEGIN	* SELECT LastName FROM CUSTOMER 
    END	^_ 

    Если процедура использует какие-либо параметры, то ее синтаксис несколько 
меняется. Вот пример такой процедуры для SQL Seiwer: 

    CREATE   PROCEDURE   listcustontersbystate(@State   char(2), 
    SLastNameMask  char(30)) AS BEGIN 
    SELECT  LastName   FROM  CUSTOMER 
    WHERE   State=@State  AND  LastName   LIKE   @LastNameMask END 

    386	Часть III. Справочные материалы 

    Сценарии 

    Нередко бывает удобно конструировать операторы языка определения данных 
(Data Definition Language — DDL), в том числе хранимые процедуры, с 
применением файлов сценариев (script) SQL. Эти файлы можно редактировать в 
любом текстовом редакторе; в большинстве хороших редакторов SQL поддерживается 
сохранение содержимого сценариев на диске. Помните, что такие сценарии должны 
содержать все необходимые операторы USE и разделители GO. Запуск сценария SQL 
Server на выполнение производится путем передачи его имени в командную строку 
утилиты ISQL. 

    ISQL  -Usa  -Imyscript.sql   -Omyscript.out 

    Параметр -i определяет имя выполняемого сценария, параметр -о — имя 
выходного файла сценария. В листинге 18.1 приведен пример сценария SQL. 
Процедура sp_dir, определенная в сценарии, генерирует список объектов, похожий 
на тот, что выводится по команде DIR операционных систем DOS и Windows. 

    Листинг 18.1. Файл сценария SQL, содержащий хранимую процедуру sp_dir /* 

    * DROP PROC dbo.sp_dir 
    */ 
    use sybsystemprocs go 
    IF OBJECT_ID('dbo.sp_dir') IS NOT NULL BEGIN 
    DROP PROC dbo.sp_dir 
    PRINT '<« DROPPED PROC dbo.sp_dir >»' END go 
    create procedure sp_dir @mask char(30) = '%', @obtype char(2) = 'U', 
@orderby char(3)='/N' as select o.id, 
    о.name, 
    o.type, 
    date_created=o.crdate, 
    row_count = rowcnt(i.doampg), 
    row_len=l*null, 
    size = convert(numeric(13),(reserved_pgs(i.id, 
i.doampg)+reserved_pgs(i.id, i.ioampg))) , 
    data_space = convert(numeric(13),data_pgs(i.id, i.doampg)), 
    index_space = convert(numeric(13),data_pgs(i.id, i.ioampg)), 
    unused_space = convert(numeric(13),((reserved_pgs(i.id, 
    i.doampg)+reserved_pgs(i.id, i.ioampg))-(data_pgs(i.id, 
i.doampg)+data_pgs(i.id, i.ioampg)))) , 
    owner=user_name(o.uid) , 
    sequencer=0.0 into #sp_dir from sysobjects o, sysindexes i 
    where о.name like @mask and oVtype like dobtype and o.id*=i.id 
    and i.indid<=l	.^ select @orderby=upper (@orderby)'' 
    if @orderby = '/N'	•+. begin 
    create clustered index sp dirind on #sp_dir (name,id) end	" 'wj>-else 
    if @orderby = '/R' begin 
    create clustered index sp_dirind on #sp_dir (row_count,id) end else 
    if Sorderby = '/S' begin 

    Глава 18. Sybase SQL Server	387 

    create clustered index sp_dirind on ttsp_dir (size,id) end else 
    if @orderby = '/D' begin 
    create clustered index sp_dirind on #sp_dir (date_created,id) end else 
    if @orderby = '/DS ' begin 
    create clustered index sp_dirind on ttsp_dir (data_space,id) end else 
    if @orderby = '/IS' begin 
    create clustered index sp_dirind on #sp_dir (index_space,id) end else 
    if Sorderby = '/US' begin 
    create clustered index sp_dirind on #sp_dir (unused_space,id) end else 
    if @orderby = '/0' begin 
    create clustered index sp_dirind on #sp_dir (owner,id) end 
    alter table #sp_dir drop sequencer 
    alter table #sp_dir add sequencer numeric(10,0) identity 
    insert into #sp_dir (name,row_count,size,data_space,index_space,unused_space) 
    select 
    'TOTAL:',row_count=sum(row_count),size=sum(size),date_space=sum(data_space),index_space 
    =sum(index_space), unused_space=sum(unused_space) 
    from fsp_dir 
    select name,type,date_created, row_count, size, data_space, index_space, 
    unused_space, owner 
    from #sp_dir 
    order by sequencer 
    go 
    IF OBJECT_ID('dbo.sp_dir') IS NOT NULL 
    PRINT '<« CREATED PROC dbo.sp_dir >»' ELSE 
    PRINT '<« FAILED CREATING PROC dbo.sp_dir >»' go 

    Процедура sp_dir может использоваться для отображения списка объектов 
любого типа, хранящихся в определенной базе данных на сервере. Список можно 
сортировать по любому полю. На рис. 18.1 приведен пример результата работы 
процедуры sp_dir. 
    Обратите внимание на оператор в начале файла, который определяет базу 
данных для хранения процедуры, а также на использование разделителя GO между 
фрагментами сценария. 

    На заметку 
    Полный текст этой процедуры находится на компакт-диске, прилагаемом к этой книге. 


    Выполнение хранимых процедур 

    Хранимые процедуры SQL Server выполняются по команде EXECUTE, которая 
имеет следующий синтаксис. 

    EXECUTE имя_процедуры параметры 

    388 Часть III. Справочные материалы 

    Слово EXECUTE можно сократить до ЕХЕС или вообще опустить его, если эта 
команда стоит в командном файле первой. Например, процедуру listcustomers 
можно запустить на выполнение в окне утилиты ISQL следующим образом: 

    listcustomers 

    iffi WISOL32 lUnlilled) on KHEN/oubs2							HtilE 
    :№:!#  Connect  Ото  ИФ 
    sp_dit-  'V.'S1 il-     V      -•••     '   '     •'••							jf 
    name	type date created					row^count    size                               
    _ 
    sysalternates	S	Jan	1   190(1	12:00:	88: 000AM	1	16 
    sysattributes	S	flug	17  1996	3:22:	15:916AM	16	16 
    syscolunns	S	Jan	1   1908	12:00:	вв:оввйМ	239	21 
    syscomments	S	Jan	1   1900	12:00:	вв:ввтш	21	16 
    sysconstraints	S	Sep	1993	11:13:	11:OOOPM	В	16 
    sysdepends	S	Jan	1900	12:OB:	ВВ: 000AM	19	16 
    sysgams	S	Jan	2000	12:00:	ВВ:ОООЙМ	0	0 
    sysindexes	S	Jan	1900	12:08:	00:000011	12	16 
    syskeys	S	Jan	1900	12:00:	00: 000ft М	51	16 
    syslogs	S	Jan	1900	12:88:	ВВ:800ЙМ	В	62 В 
    sysobjects	S	Jan	1900	12:00:	ВВ:ВВ8йМ	15	15 
    syspartitions	S	Rug	17   1996	3:22:	15:916RM	0	16 
    sysprocedures	S	Jan	1   1900	12:80:	ВВ:ОООЙМ	261	18 
    sysprotects	S	Jan	1   1900	12:OB:	00:088011	87	31 
    sysreferences	S	Sep	1993	11:43:	11:ВОВРМ	в	16 
    sysroles	S	Sep	1993	11:13:	11 : ОООРМ	0	16 
    syssegments	S	Jan	1900	12:88:	ВВ:ВВВЙМ	1	8 
    systhresholds	S	Sep	1993	11:13:	11 : ООВРН	в	16 
    systypes	S	Jan	190B	12:80:	вв:ввтм	30	16 
    sysuser messages	S	Hay	22   1992	1:07:	22:ВВВРМ	0	16 

    Рис. 18.1. Отображение списка объектов базы данных с помощью процедуры 
sp_dir 

   Параметры в хранимую процедуру можно передавать как по порядку, так и 
по именам: 
    exec   listcustomersbystate   'МО','%' 

    или 

    exec listcustomersbystate @LastNameMask='%',@State='MO' 


    Системные процедуры 

    Системная процедура — это специальная хранимая процедура, имя которой 
начинается с символов sp_. Такая процедура выполняется над текущей базой 
данных. Примером системной процедуры является sp_spaceused. При ее выполнении 
над текущей базой данных pubs2 отображается объем дискового пространства, 
занимаемого этой базой данных, а при ее выполнении над базой данных master, 
соответственно, отображается объем дискового пространства, занятый главной 
базой данных. Системные процедуры могут храниться в базах данных-master или sybsystemproc. 
    Вместо того, чтобы командой USE переключать текущую базу данных для ее 
обработки системной хранимой процедурой, можно просто поставить имя базы 
данных перед именем хранимой процедуры. Например, если необходимо выполнить 
процедуру sp dir в базе данных master, но текущей базой данных является pubs2, 
то команда будет выгпадвоъ следующим образом: 

    master..sp_dir '%' 'S1 

    Хотя процедура sp dir фактически находится в базе данных sybsystemproc, 
текущей базой данных на время выполнения процедуры станет master. Рис. 18.2 
иллюстрирует сказанное. 
    Обратите внимание на две точки между именами базы данных и процедуры, 
обычно используемые при вызове хранимых процедур Sybase. При этом параметр 
owner (который можно указать и явно) приобретает по умолчанию значение dbo. 
    
    Глава 18. Sybase SQL Server 389 

    IS WISOL32- (Untitled) on KHEN/pubs2									•••••••^••ПТпТх 
    •file • Edit ' ?oncect . Дшу -Цф .           .                       .. .. 
    master. .sp_dir   'V , 'S'                                                 
                                                                               
                             j~ 
    name	type date_created							rou_caunt    size                             
      __ 
    sysalternates	S	Jan	1	1900	12:00	:00	: 088AM	1	16 
    sysattributes	S	Аид	17	1996	3:22	:1S:916flM		83	16 
    syscharsets	S	Jul	27	1990	10:08	:32	: 76 8П 11	5	32 
    syscolumns	S	Jan	1	1900	12:00	:00	: 800AM	253	2» 
    syscomments	S	Jan	1	1900	12:08	:00	: 800AM	138	32 
    sysconf igures	S	Jan	1	1900	12:00	:80	:ODOAM	185	32 
    sysconstraints	S	Sep	1	1993	11:ii3:Ufl		: 088PM	0	16 
    syscurconf igs	S	Jan	1	1988	12:00	:00	: 000AM	8	0 
    sys databases	S	Jan	1	1900	12:88	:00	: 000AM	7	15 
    sysdepends	S	Jan	1	1900	12:00	:00	: 880AM	28	16 
    sysdeuices	S	Jan	1	1900	12:00	:80	: 088AM	18	16 
    sysengines	S	Jan	1	2000	12:00	:00	: 008AM	8	0 
    sysgans	S	Jan	1	2000	12:80	:00	: 000AM	8	8 
    sysindexes	S	Jan	1	1900	12:00	:00	: 000AM	39	16 
    syskeys	S	Jan	1	1900	12:00	:00:вООйМ		l«9	16 
    syslanguages	S	Jul	Z7	1990	18:08	:32	:760AM	0	16 
    syslisteners	S	Jan	1	1900	12:00	:00	: 088AM	8	В 
    syslocks	S	Jan	1	1900	12:00	:BO	:OBBAM	В	8 
    sysloginroles	S	Sep	1	1993	11:U3	:16	: 800PM	U	16 
    syslogins	S	Jan	1	1900	12:00	:00	:BOOAM	1»	16                              
                , 
    Puc. 18.2. Быстрый способ переключения текущей базы данных для выполнения 
хранимой процедуры 


    Триггеры 

    Триггеры (trigger) имеют определенное сходство с хранимыми процедурами, но 
в то же время отличаются от них. Это программы на языке SQL, которые 
запускаются автоматически при выполнении определенной операции над конкретной 
таблицей: вставке, обновлении или удалении данных, т.е. ассоциируются с этой 
операцией. Вот пример триггера на языке Transact-SQL: 

    CREATE TRIGGER SALEDelete ON CUSTOMER FOR DELETE 
    AS 
    BEGIN 
    DELETE FROM SALE 
    WHERE CustomerNumber=(Select CustomerNumber FROM 
    deleted) END 

    Этот триггер удаляет данные о продажах определенному покупателю из таблицы 
SALE, как только запись об этом покупателе удаляется из таблицы CUSTOMER. 
Такое удаление называется каскадным (cascading delete), поскольку одна 
операция удаления записи из таблицы вызывает каскад операций удаления данных в 
других таблицах, ассоциированных между собой по ключу. 
    Обратите внимание на использование виртуальной таблицы deleted. Во время 
выполнения триггера операции DELETE на сервере создается временная таблица под 
названием deleted, содержащая удаляемые строки. В приведенном триггере эта 
таблица используется для определения значения поля CustomerNumber в удаляемой 
записи. Затем это значение* используется для удаления строк из таблицы SALE. 
    При срабатывании триггеров операций INSERT и UPDATE на сервере создается 
похожая таблица под названием inserted. Эта таблиц%существует фактически 
только в памяти компьютера и больше нигде, но к ней можно обращаться из 
триггерсГточно так же, как и к любой другой таблице. 

    Курсоры 

    Курсоры (cursor) — это компромисс между ориентированным на множества 
подходом SQL и потребностью в построчных операциях. С помощью курсоров можно 
работать с отдельными строками таблицы. Обычно курсоры не пишутся на языке 
SQL, а автоматически создаются системой BDE, но иногда они оказываются 
удобными для использования в хранимых процедурах. 

    390 Часть III. Справочные материалы 

    Над курсорами выполняются четыре основные операции: объявление, открытие, 
извлечение данных и •зажригала. С тошящж» к^со^оъ можно также, модифицировать 
и удалять строки таблицы. 
    Объявление курсора содержит оператор SELECT и (для модифицируемых 
курсоров) список модифицируемых столбцов. Вот пример такого объявления: 

    DECLARE CUSTOMER_SELECT CURSOR FOR SELECT * FROM CUSTOMER 

    Прежде чем считывать строки, используя курсор, его необходимо открыть. Для 
инициирования запроса, содержащегося в объявлении курсора, используется 
команда OPEN. 

    OPEN CUSTOMER_SELECT 

    По команде OPEN данные в приложение не передаются. Для этого необходимо 
использовать команду 

    FETCH. 
    FETCH CUSTOMER_SELECT 

    По этой команде из возвращаемого курсором набора данных извлекается одна 
строка. Все последующие вызовы FETCH приводят к извлечению очередных строк. В 
курсорах SQL Server поддерживается только одностороннее продвижение по записям 
таблицы: с помощью команды FETCH нельзя возвращаться к ранее пройденным 
записям. Для этого необходимо закрыть курсор командой CLOSE и снова открыть 
его командой OPEN. 

    На заметку 
    Отсутствие в SQL Server поддержки двунаправленных курсоров — еще не повод 
не использовать их в приложениях Delphi. Система BDE эмулирует двунаправленные 
курсоры на уровне приложений-клиентов независимо от того, поддерживаются ли 
они платформой сервера. Вот почему по таким структурам данных, как TQuery и 
ттаЫе, можно передвигаться как вперед, так и назад. 

    Строки, полученные из модифицируемого курсора, можно модифицировать с 
помощью специальных версий команд UPDATE и DELETE. Модифицируемый курсор 
объявляется с использованием ключевого слова FOR UPDATE OF. Вот пример такого объявления: 

    DECLARE CUSTOMERJJPDATE CURSOR FOR SELECT * FROM CUSTOMER FOR UPDATE OF LastName 


    На заметку 
    В списке ключевого слова FOR UPDATE OF следует перечислять только те 
столбцы, которые на самом деле будут модифицироваться. Наличие в этом списке 
лишних столбцов замедляет работу сервера. 

    Для удаления или модифицирования текущей строки курсора в дополнение к 
команде DELETE или UPDATE используется синтаксическая конструкция WHERE 
CURRENT OF имя_курсора, как в следующем примере: 

    UPDATE CUSTOMER 
    SET LastName="Cane"        * 
    WHERE CURRENT OF CUSTOMERJJPDATE 

    или	•*•*. 

    DELETE FROM CUSTOMER 
    WHERE CURRENT OF СиЗТОМЕ%Щ?ОАТЕ 

    Для завершения работы курсора его закрывают командой CLOSE. Вот ее синтаксис: 

    CLOSE CUSTOMERJJPDATE 

    Закрытие курсора не приводит к освобождению системных ресурсов, которые он 
использовал. Для этого применяется команда DEALLOCATE. 

    DEALLOCATE CUSTOMER UPDATE 

    Глава 18. Sybase SQL Server 391 

    Резюме 

    Из этой главы вы узнали, как запустить систему Sybase SQL Server, как 
подключиться к серверу как выявить и устранить возможные проблемы при 
подключении. Глава содержит достаточно подробное введение в диалект 
Transact-SQL для Sybase SQL Server. 

    Что дальше... 

    В главе 19, "Отчеты", рассматривается создание отчетов Delphi в среде 
клиент-сервер — от простейших списков до сложных многотабличных отчетов. 

    392 Часть III. Справочные материалы 
