Ключевые слова:mysql, firebird, convert, database, (найти похожие документы)
From: Landgraph <landgraph@inbox.ru.>
Newsgroups: http://www.landgraph.ru/
Date: Mon, 9 Dec 2007 14:31:37 +0000 (UTC)
Subject: Особенности перехода с MySQL на InterBase (FireBird)
Оригинал: http://www.realcoding.net/articles_html/mysql2interbase.html
Несмотря на постоянное развитие MySQL, существует определенный круг
задач, когда необходимо пользоваться другими СУБД. К тому же, MySQL
все больше перерастает в платный продукт и не все программисты имеют
возможность внедрять в свои разработки сервера MySQL. Также, MySQL
несколько отстает в развитии от того же InterBase: когда в InterBase
уже вовсю использовались триггеры, хранимые процедуры, домены и т.п. -
в MySQL это все только зарождалось.
Вне зависимости от того, чем вызвано использование InterBase, при
переходе от MySQL можно наткнуться на несколько подводных камней.
Основные из них и способы их обхода будут рассмотрены в данной статье.
Домены как средство упрощения проектирования БД
При проектировании БД в MySQL необходимо явное задание типов столбцов
при создании таблиц. Поэтому, необходимо помнить все типы столбцов. В
InterBase существует способ облегчения проектирования - домены
(Domains). Домены - это псевдонимы типов (Aliases), которые удобно
использовать.
Например, существуют две таблицы "Пользователи" и "Действия
пользователей". Первая из них содержит данные "Идентификатор
пользователя" (C_ID), "Имя пользователя" (C_NAME). Вторая таблица
содержит поля "Идентификатор пользователя" (C_ID), "Описание действия"
(A_DESCRIPTION). Как видно, у обоих таблиц есть связующее поле -
"Идентификатор пользователя". В обычном случае текст создания таблиц
выглядит так:
CREATE TABLE users (
C_ID INT(11),
C_NAME VARCHAR(64)
)
CREATE TABLE actions (
C_ID INT(11),
A_DESCRIPTION BLOB
)
Как видите, поля дублируются, но при их написании можно ошибиться в
размере поля, написав во второй таблице вместо INT(11) - INT(12).
Сразу результат может быть незаметен, но при работе приложения могут
возникнуть "непонятные" проблемы. Когда, например, два столбца
оказываются в UNION запросе и выходят "непонятные" ошибки, казалось бы
в правильно составленном запросе. В InterBase все решается несколько
подругому.
CREATE DOMAIN CLIENT_ID AS INTEGER
CREATE DOMAIN CLIENT_NAME AS VARCHAR(64)
CREATE DOMAIN ACTION_DESCRIPTION AS BLOB
CREATE TABLE users (
C_ID CLIENT_ID,
C_NAME CLIENT_NAME
)
CREATE TABLE actions (
C_ID CLIENT_ID,
A_DESCRIPTION ACTION_DESCRIPTION
)
Таким образом, InterBase, с помощью объявления прототипов полей,
позволяет избавиться от лишней головной боли. Тем не менее, остается
возможность создания таблиц и в обычном режиме, при этом домены
создаются автоматически, но без явной связи.
Замена автоинкрементных полей
В отличие от MySQL, в InterBase нет автоинкрементных полей как
таковых. Вначале, этот факт доставляет больше проблем, чем решений.
Но, у такого подхода есть и преимущества. Во-первых - это возможность
создания нескольких автоинкрементных полей для одной таблицы.
Во-вторых, возможность управления увеличением автоинкрементных полей.
Рассмотрим подробнее создание таблицы с автоинкрементным полем.
Возьмем таблицу пользователей, в ней поле "Идентификатор пользователя"
должно быть автоинкрементным.
Во-первых, необходимо создать генератор. Генератор - это переменная, в
которой храниться значение автоинкремента.
CREATE GENERATOR GEN_CLIENTS
Теперь, необходимо определиться, каким образом мы будем добавлять
новые строки в таблицу.
Первый вариант - когда значение автоинкрементного поля в дальнейшем не
используется. Т.е., сразу после добавления записи мы больше не будем
пользоваться этим идентификатором.
В этом случае, самым простым решением является создание триггера для
установки значения автоинкрементного поля.
CREATE TRIGGER TRI_CID FOR USERS BEFORE INSERT POSITION 0 AS
BEGIN
IF (NEW.C_ID IS NULL ) THEN
NEW.C_ID = GEN_ID(GEN_CLIENTS, 1);
END
Именно такая конструкция позволяет: если значение поля не передано
явно (IF (NEW.C_ID IS NULL) THEN), то устанавливается новое значение
поля (NEW.C_ID = GEN_ID(GEN_CLIENTS, 1);). Изменение значения
генератора осуществляется командой GEN_ID(GEN_CLIENTS, 1), первый
параметр которой - имя генератора, который мы создали заранее, второй
параметр - на сколько необходимо увеличить генератор.
Вот одно из отличий от автоинкрементных полей MySQL. Если в MySQL
автоинкремент увеличивается только на 1, то в InterBase это задается
пользователем. Можно сделать, что увеличение будет на произвольное
число, 2 (GEN_ID(GEN_CLIENTS, 2)), 3 (GEN_ID(GEN_CLIENTS, 3)), 10
(GEN_ID(GEN_CLIENTS, 10)) и т.п.
Все, теперь после добавления новой записи поле будет автоматически
увеличено на заданное число.
Второй вариант - когда необходимо использовать значение
автоинкрементного поля сразу после добавления в базу. Например, когда
в таблицу действий необходимо сразу добавить запись, привязанную к
вновь созданному пользователю. В этом случае нет необходимости
создавать триггер, т.к. перед вставкой записи мы будем получать
значение автоинкрементного поля. Для этого необходимо воспользоваться
следующим запросом:
SELECT GEN_ID(GEN_CLIENTS, 1) FROM RDB$ DATABASE
Этот запрос вернет значение автоинкрементного поля для новой записи.
Другими словами, в MySQL мы могли узнать значение автоинкрементного
поля только после добавления записи и потом пользоваться им. А в
InterBase мы можем получить это значение заранее, до вставки очередной
записи.
Задача миграции с MySQL на InterBase не имеет,
хотя безусловно некоторым организациям приходится
принимать такие решения в связи с причинами
известными только им. Было бы более полезно
(ИМХО) описать процедуру миграции с InterBase на
MySQL 5.x.x, т.к. там появились stored procedures,
т.к. тендеция к замене InterBase в целом происходит
уже давно.