Автор: Андрей Волков
В отличие от очень многих СУБД FileMaker не поддерживает управление данными с помощью языка структурированных запросов SQL. Несмотря на то, что в 12 версии в FileMaker была введена функция Execute SQL, разработчики получили лишь возможность извлекать с ее помощью данные в простом текстовом виде.
Такие операции, как UPDATE, INSERT, DELETE (то есть обновление, добавление и удаление записей), с помощью Execute SQL выполнить невозможно.
Начиная с 13 версии, с появлением команды Perform Script On Server, эта проблема несколько потеряла свою актуальность. Команда в принципе позволяет выполнить названные выше операции, хотя и несколько варварским методом: для каждой операции приходится создавать и хранить отдельный скрипт.
Мне хотелось бы в очередной раз обратить внимание разработчиков на возможности PHP расширения, поскольку это весьма эффективный инструмент, позволяющий развить возможности системы. В нашем случае PHP позволяет реализовать полноценное управление данными с помощью SQL . А бонусом является возможность управлять транзакциями.
Под PHP расширением в данном случае мы будем понимать специальный php-файл, который мы подложим на сервер в папку C:\Program Files\FileMaker\FileMaker Server\Web Publishing\web-server-support\test\fmi-test\
И к которому сможем обратиться через веб-запрос: http://hostipaddress/fmi-test/sql.php
Этот файл будет обращаться к базам данных файлмейкер, используя подключение ODBC. Чтобы это стало возможным, необходимо на сервере (там же, где размещен php файл):
- установить ODBC драйвер для файлмейкера,
- в настройках файлмейкер сервера разрешить подключение по ODBC и активизировать Web Engine,
- в самих базах данных создать акаунт с привилегией Access via ODBC.
Драйвер FileMaker ODBC driver входит в дистрибутив файлмейкер сервера. Там два дистрибутива: для 32-х и для 64-битных приложений. Скорее всего, потребуется 32-битный драйвер, но можно не особо смущаясь инсталлировать оба. Процесс инсталляции не требует никаких специальных знаний.
Я бы также порекомендовал для всех баз данных использовать один и тот же акаунт для odbc подключений. В этом случае логин и пароль можно попросту «записать» в php файл. Тогда для запуска SQL потребуется только указать два параметра: имя файла базы данных, в котором выполняем запрос, и собственно текст запроса (так называемый SQL стейтмент).
Про запуск SQL мы уже говорили в одной из предыдущих статей: используется команда Insert From URL ($url), в которой $url будет собираться следующим образом:
«http://hostipaddress/fmi-test/sql.php?db=» & $filename & «&sql=» & GetAsUrlEncoded($sql)
Где переменная $filename передает имя базы данных, а переменная $sql собственно содержит sql-запрос.
Например, удалить все записи из таблицы test_table в файле my_test_ db поможет следующий веб-запрос:
http://hostipaddress/fmi-test/sql.php?db=my_test_db&sql=DELETE%20ALL%20FROM%20test_table
Давайте теперь рассмотрим файл sql.php, который будет выполнять все наши распоряжения.
Предлагаю к конечному варианту приближаться всем вместе постепенно, это позволит освоить основы php и работать далее самостоятельно.
Шаг 1. Подключение к базе данных по ODBC (http://hostipaddress/fmi-test/sql.php)
<?php
// Замените параметры подключения на ваши актуальные значения //
$conn = odbc_connect(«DRIVER={FileMaker ODBC};Server=109.100.100.10;Database=my_db;», «login», «password»);
odbc_close($conn);
?>
Замените параметры подключения на ваши актуальные значения.
Итак, в нашем файле всего две строки. Первая открывает соединение по ODBC, вторая закрывает это соединение. Как нам проверить, что у нас все работает? Давайте выводить в браузер результат нашей работы
<?php
$conn = odbc_connect(«DRIVER={FileMaker ODBC};Server=109.100.100.10;Database=my_db;», «login», «password»);
odbc_close($conn);
echo $conn; // выводит в окно браузера содержимое переменной $conn
?>
Если все настроено правильно, то в браузере мы увидит такое сообщение: Resource id #1
Шаг 2. Попробуем выполнить какой-нибудь sql запрос
<?php
$conn = odbc_connect(«DRIVER={FileMaker ODBC};Server=109.100.100.10;Database=my_db;», «login», «password»);
$rs = odbc_exec($conn,’INSERT INTO my_test_table (test_field) Values(66)’);
odbc_close($conn);
echo $rs; // выводит в окно браузера содержимое переменной $rs
?>
Проверить работу просто. В браузере мы увидим: Resource id #2
В самой же базе данных в таблице my_test_table будет создана новая запись, в которой поле test_field будет значение 66
Пару слов про транзакции. По умолчанию режим транзакций отключен. То есть выполнение команды odbc_exec() ведет непосредственно к изменению состояния базы данных. Но для нашего примера этот режим особо и не нужен, ведь мы выполняем всегда всего лишь один запрос, а не последовательность запросов. При выполнении групповой операции, например, обновлении или удалении группы записей, команда и так не будет выполнена, если хотя бы одна из записей заблокирована пользователем.
Тем не менее, если кому потребуется, включить транзактный режим он сможет следующим образом:
<?php
error_reporting(0); // отключаем вывод системных сообщений об ошибке
$conn = odbc_connect(«DRIVER={FileMaker ODBC};Server=109.100.100.10;Database=my_db;», «login», «password»);
odbc_autocommit($conn, false); // отключаем автосохранение после каждого запроса
$rs = odbc_exec($conn,’UPDATE my_test_table SET test_field = 66′);
$rs2 = odbc_exec($conn,’UPDATE other_table SET any_field = 77′);
$error = odbc_errormsg($conn); // проверяем, была ли получена ошибка при выполнении запроса
if (!empty($error)) {
echo «ERROR » . $error;
odbc_rollback($conn); // откат транзакции, если хотя бы один из запросов невозможно выполнить
} else {
odbc_commit($conn); // коммит транзакции
echo «OK»;
}
odbc_close($conn);
?>
Заодно в этом примере мы сделали обработку ошибок. Теперь если запрос выполнен успешно, в браузере отобразится ОК; если же одна из записей была заблокирована, то увидим:
ERROR [FileMaker][FileMaker] (301): Record is locked by another user
Шаг 3. Теперь мы должны изменить наш файл. Сделаем так, чтобы php-файл считывал SQL-стейтмент, переданный в запросе, и сразу выполнял его, сообщая об успехе или ошибке выполнения.
<?php
error_reporting(0); // отключаем вывод системных сообщений об ошибках
if ( isset($_GET[‘sql’])) { $sql = $_GET[‘sql’]; } else {exit;}
if ( isset($_GET[‘db’])) { $db = $_GET[‘db’]; } else {exit;}
$host = «109.100.100.10»; // подставьте ваши реальные данные
$login = «login»; // подставьте ваши реальные данные
$password= «password»; // подставьте ваши реальные данные
$conn = odbc_connect( «DRIVER={FileMaker ODBC};Server=» . $host . «;Database=» . $db . «;», $login, $password);
$rs = odbc_exec($conn,$sql);
$error = odbc_error($conn); // проверяем, была ли получена ошибка при выполнении запроса
if (!empty($error)) {
echo «ERROR » . $error;
} else {
echo «OK»;
}
odbc_close($conn);
?>
Вот и все. Успешных шагов!
Великолепная статья!
Вопрос — а запросы изменяющие структуру базы, типа CREATE TABLE и ALTER TABLE — будут работать? То есть можно ли изменить таким образом структуру таблиц из скрипта самого FileMaker?
‘ALTER TABLE roles ADD mydate date’
‘ALTER TABLE roles ADD mytext varchar’
эта инструкция работает. Только в голову не приходит, зачем это нужно. Ведь лэйауты все равно не создать, да и насчет реляций не уверен.
Ну например, для объединения данных из разных таблиц в одну (UNION) для последующего экспорта. Это гипотетический пример.
Реляции вы, конечно, не создадите, они же не командами SQL делаются, это что-то внутренне FM, насколько я понимаю.
мне кажется, полной и удобной автоматизации здесь не достичь.
экспортировать можно в CSV
Вопрос был скорее гипотетический — позволяет ли FileMaker, менять структуры базы с помощью SQL запроса, а не Manage Database. Выяснили — позволяет. Запомним на будушее — может пригодится.
Важное дополнение.
Если мы приконнектились к некоему файлу базы данных, то ODBC запросы возможны не только для физических таблиц, которые в этом файле имеются, но вообще в отношении всех логических таблиц, которые вынесены в Relationships Graph. То есть в рамках одной сессии (транзакции) можно получать данные и изменять данные в таблицах нескольких разных файлов. Это весьма и весьма удобно.