Firebird Documentation IndexПереход с MS SQL на Firebird → Синтакс SQL
Firebird Home Firebird Home Пред.: Типы данныхFirebird Documentation IndexУровень выше: Переход с MS SQL на FirebirdСлед.: Трюки с SQL

Синтакс SQL

Основы использования баз данных
Использование переменных
Управляющие конструкции
Стандартные операторы
Использование транзакций
Использование курсоров

Этот раздел описывает основные различия в синтаксе языка SQL, используемого СУБД Firebird и MS SQL.

СУБД Firebird и MS SQL могут ссылаться на объекты базы данных (таблицы, поля и т.д.) по их именам напрямую, если имена объектов не содержат пробелы и другие недопустимые в прямой ссылке символы (например, нелатинские буквы). Для использования пробелов и других символов СУБД MS SQL использует квадратные скобки, [ и ], а СУБД Firebird использует двойные кавычки, ". Еще одно различие - возможность использования в СУБД MS SQL схемы для ссылки на объект: база_данных.владелец_объекта.объект. СУБД Firebird не допускает такой нотации.

Внимание

СУБД MS SQL использует регистро-зависимые имена объектов, если при установке Вы выбрали использование различения регистра символов; в противном случае, имена объектов регистро-независимы. Весело? Не очень...

Подсказка

СУБД MS SQL способна работать с идентификаторами, имена которых заключены в двойные кавычки, но по умолчанию эта возможность доступна только при доступе через OLE DB и ODBC, но не при доступе через DB-Library. По этой причине такую практику работы следует избегать.

СУБД MS SQL 7 и выше поддерживает обновляемые соединения (joins) (обновление, удаление, вставка). СУБД Firebird не распознает такой синтакс.

Типы даных, конечно, различаются. Хотя обе СУБД имеют общее подмножество наиболее часто используемых типов. Этот вопрос редко вызывает проблемы при переносе базы данных.

Различаются встроенные функции. Большинство из встроенных функций СУБД MS SQL можно заменить в СУБД Firebird использованием функций, определяемых пользователем (UDFs).

Различаются форматы указания строковых констант для дат. СУБД Firebird принимает строки различных форматов, вне зависимости от используемой платформы. СУБД MS SQL, в свою очередь, использует совмещение серверо-независимых, серверо-платформенных форматов и формата настройки клиентского соединения. Дополнительно, методы доступа СУБД MS SQL обычно вводят один или два уровня, в которых строковая константа может быть преобразована в дату тем или иным образом.

В СУБД MS SQL можно определять бОльшее количество переменных окружения, чем в СУБД Firebird, но наиболее общие можно найти и в СУБД Firebird (извлечение идентификатора и имени пользователя). Единственная важная переменная, которая отсутствует в СУБД Firebird, - это переменная, возвращающая количество строк последней операции (с версии 1.5 СУБД Firebird такая переменная введена - прим. перев.).

Важное различие было в том, что СУБД Firebird 1.0 не поддерживала оператор CASE СУБД MS SQL. Иногда можно было заменить его функциональность использованием хранимой процедуры. Начиная с версии 1.5, СУБД Firebird поддерживает использование оператора CASE.

Небольшое различие между СУБД еще и в том, что СУБД MS SQL не использует разделителей для операторов, что может служить источником трудно обнаруживаемых ошибок при переходе, особенно при использовании множества скобок. СУБД Firebird в скриптах требует завершать каждый оператор точкой с запятой (если не определен другой разделитель - прим. перев.), поэтому ошибки легче обнаружить.

Обе СУБД MS SQL и Firebird поддерживают комментарии, заключенные между разделителями /* и */. СУБД MS SQL также поддерживает синтакс «два дефиса» -- для однострочного комментария. Некоторые утилиты для СУБД Firebird также поддерживают такой синтакс.

Основы использования баз данных

СУБД MS SQL позволяет клиентам обращаться к нескольким базам данных через одно и то же соединение. Для этого при обращении к объектам баз данных необходимо использовать нотацию база_данных.владелец_объекта.объект, либо явно использовать оператор USE.

СУБД Firebird не допускает использование нескольких баз данных в одном операторе SQL. Однако эта СУБД позволяет клиенту работать с транзакциями, охватывающими несколько баз данных.

Существует много утилит для ввода и выполнения операторов SQL для обоих платформ. Имейте в виду, что для СУБД Firebird не нужно вводить команду GO для разделения пакетов команд, как для пакетов T-SQL - Вы обычно управляете транзакциями явно. Также, Вы можете для обоих СУБД использовать настройку «подтверждать (commit) каждый оператор».

Внимание

Если Вы установили СУБД MS SQL и Firebird на один компьютер, будьте внимательны при использовании утилиты isql. Если Вы не указываете при запуске этой утилиты полный путь, будет запущена та, что первой будет найдена по путям для поиска файлов, а обе СУБД имеют в своем составе программу с именем isql.

Использование переменных

Управление переменными схоже на обоих платформах. Переменные необходимо объявлять до их использования, а также указать их тип. В СУБД Firebird нет необходимости добавлять к имени переменной префикс @, а также переменные обязательно должны быть объявлены до тела хранимой процедуры или триггера.

Например, сравните следующие части кода.

/* MS-SQL */
CREATE PROCEDURE my_procedure
AS
DECLARE @my_variable int
SET @my_variable = 5
/* Firebird */
CREATE PROCEDURE my_procedure
AS
DECLARE VARIABLE my_variable int;
BEGIN
  my_variable = 5;
END 

В обоих СУБД параметры считаются обычными переменными с установленным начальным значением.

Управляющие конструкции

BEGIN..END

В обоих СУБД ключевые слова BEGIN и END могут использоваться для объединения нескольких операторов в один блок, например, при использовании в условном операторе IF.

GOTO

СУБД Firebird не имеет оператора GOTO. Однако, как правило, это к лучшему. Оператор GOTO обычно используется СУБД MS SQL, потому что по умолчанию возникающие при выполнении операторов ошибки не откатывают транзакции, необходимо после выполнения каждого оператора проверять значение переменной @@ERROR; оператор GOTO используется для объединения в группы операторов управления ошибками. В СУБД Firebird используется более удачный механизм управления ошибками - оператор WHEN...DO.

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

IF

Оператор IF..ELSE в СУБД Firebird имеет ту же семантику, что и в СУБД MS SQL, однако синтакс СУБД Firebird требует наличия ключевого слова THEN после условия.

IF (something = 'unknown')
  THEN something = 'uuhhh.....';
  ELSE something = 'I know! I know!';  

CASE

СУБД Firebird 1.0 не поддерживает оператор CASE, поэтому Вам необходимо будет сделать дополнительную работу по переносу, если Вы использовали этот оператор в базе данных СУБД MS-SQL.

Вы можете пропустить этот раздел, если Вы используете СУБД Firebird 1.5 или более новую версию, так как, начиная с версии 1.5, СУБД Firebird имеет поддержку оператора CASE.

Оператор CASE используется аналогично оператору switch языка C или оператору case языка Pascal для замены одного значения на другое. Обычно в СУБД Firebird 1.0 эту операцию можно эмулировать хранимой процедурой, возвращающей некоторое значение.

/* Это исходный оператор MS SQL,
   использующий традиционную базу данных pubs. */
CREATE PROCEDURE list_states
AS
SELECT
  CASE state
    WHEN 'CA' THEN 'California'
    WHEN 'UT' THEN 'Utah'
    ELSE 'unknown'
  END
FROM authors 
/* Это вариант перевода в СУБД Firebird 1.0. */
/* Выделить оператор CASE. */
CREATE PROCEDURE get_state_name ( state_code char(2) )
RETURNS ( state_name varchar(64) )
AS
BEGIN
 IF (state_code = 'CA') THEN state_name = 'California';
 ELSE IF (state_code = 'UT') THEN state_name = 'Utah';
 ELSE state_name = 'unknown';
END

/* Это процедура-выборка. */
CREATE PROCEDURE list_states
RETURNS (state varchar(64))
AS
DECLARE VARIABLE short_state CHAR(2);
BEGIN
  FOR SELECT state FROM authors INTO :short_state DO
  BEGIN
    EXECUTE PROCEDURE get_state_name :short_state
    RETURNING_VALUES :state;
    SUSPEND;
  END
END 

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

Еще раз: с версии 1.5 СУБД Firebird полностью поддерживает оператор CASE, поэтому, в принципе, необходимости перехода на использование хранимых процедур нет.

WHILE

Оператор WHILE существует в обоих СУБД Firebird и MS SQL, но с некоторыми различиями. Не существует операторов BREAK или CONTINUE, но их можно эмулировать при помощи дополнительных конструкций. Так же есть небольшое различие в используемом синтаксисе: СУБД Firebird требует наличия ключевого слова DO после условия цикла. Сравните следующие эквивалентные части кода.

/* Синтакс Firebird. */
WHILE (i < 3) DO
BEGIN
  i = i + 1;
  j = j * 2;
END 
/* Синтакс MS SQL. */
WHILE (i < 3)
BEGIN
  SET @i = @i + 1
  SET @j = @j * 2
END  

RETURN

Оператор RETURN в СУБД MS SQL возвращает значение целочисленной переменной и прекращает выполнение. В СУБД Firebird существует оператор EXIT, который передает управление на заключительный END хранимой процедуры. Однако здесь нет скрытой возвращаемой переменной, поэтому, если Вам необходимо вернуть некоторое значение (что опционально в СУБД MS SQL), Вы должны явно объявить возвращаемую переменную в процедуре.

WAITFOR

Оператор WAITFOR в СУБД MS SQL приостанавливает выполнение на некоторое время или до наступления указанного времени. Что-то подобное можно осуществить при помощи функций, определяемых пользователем (UDFs), в СУБД Firebird. Но в обоих СУБД использование такого оператора следует исключить, поскольку взаимодействие с клиентом полностью приостанавливается (в СУБД Firebird это может привести и к приостановке обслуживания всех соединений, а не только соединения, вызвавшего аналог указанного оператора - прим. перев.).

Стандартные операторы

Стандартными операторами, имеющимися в обоих СУБД, являются SELECT, INSERT, UPDATE и DELETE. СУБД Firebird и MS SQL поддерживают их, но в СУБД MS SQL есть несколько нестандартных расширений этих операторов, о которых необходимо рассказать на случай их использования.

В СУБД Firebird оператор SELECT не позволяет использовать ключевое слово INTO для создания новой таблицы «на лету». Вместо этого, ключевое слово INTO используется для связи результата запроса с переменной.

/* Синтаксис MS SQL для присваивания значения поля переменной. */
SELECT @my_state = state
FROM authors
WHERE auth_name = 'John'
/* Синтаксис Firebird. */
SELECT state INTO :state /* --> обратите внимание на
                            ":" перед именем переменной */
FROM authors
WHERE auth_name = 'John'

В СУБД MS SQL 7 и выше в операторе SELECT можно указвать спецификатор TOP для органичения возвращаемого набора данных. Эта функция в настоящий момент находится в стадии разработки для СУБД Firebird. (Спецификаторы FIRST и SKIP в СУБД Firebird введены, начиная с версии 1.5. - прим. перев.)

Обе СУБД MS SQL и Firebird поддерживают обычный синтаксис оператора INSERT и оператора INSERT..SELECT.

Обе СУБД MS SQL и Firebird поддерживают обычный синтаксис оператора UPDATE. СУБД MS SQL также поддерживает синтаксис оператора UPDATE, в котором выполняется соединение (join) и производится обновление одной из таблиц соединения. Можно думать об этом как об условии WHERE на стероидах. Если такая функция очень нужна, то ее можно реализовать в СУБД Firebird с использованием представлений (views).

Обе СУБД MS SQL и Firebird поддерживают обычный синтаксис оператора DELETE. СУБД MS SQL также поддерживает оператор TRUNCATE TABLE, который более эффективен (но и опаснее), чем оператор DELETE. (СУБД MS SQL также поддерживает синтаксис оператора DELETE, в котором выполняется соединение. - прим. перев.)

/* Синтаксис MS SQL для удаления всех записей my_table. */
TRUNCATE TABLE my_table /* ...или... */
DELETE FROM my_table 
/* Синтаксис Firebird. */
DELETE FROM my_table 
 

Самая большая угроза - действовать «методом тыка». Больше всего данных было утеряно командами "delete from xxx" и последующей "ой!", чем продуманной командой "delete from rdb$pages".

 
  --Jim Starkey

Использование транзакций

В СУБД Firebird в DSQL (dynamic SQL) транзакции «напрямую» не используются. Именованные транзакции в этом случае недоступны совсем. (Операторы DSQL выполняются в контексте транзакций, запущенных и контролируемых клиентским приложением.- прим. перев.) Синтаксис обоих СУБД поддерживает ключевое слово WORK для совместимости.

В большинстве случаев проблем с транзакциями не должно возникать: явное управление транзакциями «на месте» в СУБД MS SQL используется обычно из-за отсутствия поддержки управлением через исключения (exceptions).

Подсказка

В СУБД MS SQL есть глобальная переменная XACT_ABORT, которая управляет откатом транзакции при возникновении ошибки времени выполнения (run-time error). В противном случае Вам необходимо проверять значение переменной @@ERROR после выполнения каждого оператора.

В общем, большинство проблем, связанных с уровнями изоляции транзакций в СУБД MS SQL, пропадают при переходе на СУБД Firebird. Соперничество между «читателями» и «писателями» минимально за счет использования многоверсионной архитектуры (multigeneration architecture, MGA).

Использование курсоров

В СУБД MS SQL курсоры используются, в основном, для перемещения по результатам запросов, чтобы выполнить с этими результатами некоторые действия. Кроме синтаксиса, нет большой разницы для выполнения одной и той же задачи. Хотя существуют опции для перемещения вперед и назад, на практике используются, по большей части, однонаправленные курсоры.

/* Синтакс MS SQL. */
DECLARE my_cursor CURSOR
FOR SELECT au_lname FROM authors ORDER BY au_lname
  DECLARE @au_lname varchar(40)
  OPEN my_cursor
  FETCH NEXT FROM my_cursor INTO @au_lname
  WHILE @@FETCH_STATUS = 0
  BEGIN
    /* Сделать что-то интересное с @au_lname. */
    FETCH NEXT FROM my_cursor
  END
CLOSE my_cursor
DEALLOCATE my_cursor 
/* Синтакс Firebird. */
DECLARE VARIABLE au_lname VARCHAR(40);
  ...
  FOR SELECT au_lname FROM authors
  ORDER BY au_lname INTO :au_lname DO
  BEGIN
    /* Сделать что-то интересное с au_lname. */
  END 

Заметьте, что СУБД MS SQL может размещать курсоры в переменных, и передавать эти переменные как параметры; это невозможно в СУБД Firebird.

Внимание

Различные версии СУБД MS SQL имеют различные области видимости для переменных-курсоров. Будьте осторожны при их использовании и при переносе кода.

Пред.: Типы данныхFirebird Documentation IndexУровень выше: Переход с MS SQL на FirebirdСлед.: Трюки с SQL
Firebird Documentation IndexПереход с MS SQL на Firebird → Синтакс SQL