Подключение таблиц PostgreSQL к базе данных MS AccessИсточник: mccinet
При создании многопользовательского приложения важно сделать процесс его распространения по рабочим местам как можно проще. Важная часть этой проблемы - обеспечение программного подключения таблиц к источнику данных. Если данные хранятся в базе MS Access, то всё просто, но при использовании любого SQL-сервера задача заметно усложняется. Основная проблема заключается в том, что для присоединения таблицы или представления с сервера требуется установить ODBC-драйвер и зарегистрировать в системе так называемое имя источника данных (Data Source Name, DSN), которое служит для хранения специфической информации о конкретном соединении, обеспечиваемом драйвером. Если приложению требуются соединения с различными серверами, базами данных или просто отличающиеся какими-либо параметрами, то потребуется создать несколько DSN. Вручную сделать всё это очень просто. Достаточно запустить программу установки ODBC драйвера, а потом создать все нужные DSN с помощью Администратора источников данных ODBC, который находится в панели управления Windows. Проблема в том, что когда пользователей много, данная нехитрая процедура превращается в целое мероприятие. Как же автоматизировать этот процесс? Ну, с установкой драйвера всё достаточно просто: надо скопировать на компьютер пользователя необходимые файлы и добавить ключи в реестр Windows. Какие именно - зависит от самого драйвера. Это, конечно, может вызвать затруднения, однако, в крайнем случае, установить драйвер можно вручную один раз, а обновление версий проводить автоматически, как правило, заменой единственного файла динамической библиотеки. Создать DSN ещё проще. В MS Access есть специальная функция для регистрации нового источника данных: DBEngine.RegisterDatabase <Имя источника данных>, _ <Название ODBC драйвера>, _ <Выводить или нет окно диалога драйвера ODBC>, _ <Список атрибутов> Этим возможности Access и ограничиваются. Получить список источников данных и, тем более, значения отдельных параметров каждого источника с помощью встроенных средств MS Access невозможно. Однако не беда, процедуру RegisterDatabase можно запускать при каждом старте программы и, если Вы захотите установить другие значения параметров соединения, они просто будут перезаписаны поверх старых. Дальше, надо собственно подключить внешние таблицы и представления к базе данных Вашего приложения. Тут есть два пути: первый - простой, но менее гибкий и, возможно, более интерактивный. Он предполагает использование команды DoCmd.TransferDatabase с типом преобразования acLink. Подробное описание приводится в справочной системе MS Access. Второй путь сложнее, но позволяет полностью программно контролировать присоединение таблицы и заключается в создании нового объекта TableDef. Рассмотрим этот способ подробнее. Перед тем, как подключать таблицу, проверим нашу базу данных на предмет существования объекта с таким же именем, например, этой функцией: Function IsTableExist(TableName As String) As Long ' Функция возвращает следующие коды: ' 0 - Ни таблицы ни запроса с указанным именем не существует. ' 1 - Существует локальная таблица с указанным именем. ' 2 - Существует присоединённая таблица с указанным именем. ' 3 - Существует запрос с указанным именем. On Error Resume Next Dim db As Database Dim td As TableDef Dim qd As QueryDef IsTableExist = 0 err.Clear Set db = CurrentDb Set td = db.TableDefs(TableName) If err.Number = 0 Then If td.Connect = "" Then 'Таблица локальная IsTableExist = 1 Else 'Таблица присоединенная IsTableExist = 2 End If Set td = Nothing Set db = Nothing Exit Function End If err.Clear Set qd = db.QueryDefs(TableName) If err.Number = 0 Then IsTableExist = 3 'Запрос Set qd = Nothing Set db = Nothing End Function Если эта функция показала, что существует локальная таблица или запрос с таким же именем, как у таблицы, которую мы хотим подключить, то прекращаем все дальнейшие действия. Если же существует присоединённая таблица, удалим её и продолжим, как и в случае отсутствия объекта с указанным именем. Теперь наша задача - создать объект TableDef таким образом, чтобы он оказался присоединённой таблицей, полностью пригодной для любых операций с данными. Сначала создадим сам объект TableDef: Set NewTableDef = CurrentDB.CreateTableDef("Имя таблицы в БД MS Access") NewTableDef.Connect = "Строка подключения" NewTableDef.SourceTableName = "Имя таблицы или представления на сервере" Как видите, нет необходимости специально указывать, что мы хотим создать именно присоединённую таблицу ODBC. Access сам определяет это анализируя строку подключения. О том, как её правильно сформировать - чуть позже. Теперь добавим только что созданное определение таблицы в коллекцию TableDefs: CurrentDB.TableDefs.Append NewTableDef И в конце поможем Access'у определить первичный ключ, если он сам его не распознал, что является нормальным явлением при подключении представлений (VIEW): CurrentDB.Execute "CREATE UNIQUE INDEX PrimaryKey ON " & _ "Имя таблицы в БД MS Access" & "(" & _ "Список полей первичного ключа" & ")" Самое сложное здесь - составить строку подключения. В начале обязательно нужно указать "ODBC;", затем - имя источника данных ("ODBC;DSN=<Имя источника данных>;..."), имя пользователя ("...;UID=<Логин>;...") и пароль ("...;PWD=<Пароль>;...") например: "ODBC;DSN=PostgreSQL Test;UID=Postgres;PWD=secret;" Далее, при необходимости, можно указать имя базы данных и другие параметры, в том числе, специфичные для используемого ODBC драйвера. Порядок следования опций не имеет особого значения, так как все они различаются по именам (DSN, UID, DB). В качестве разделителя используется точка с запятой (;). Например: NewTableDef.Connect = "ODBC;DSN=PG_Sample;DATABASE=sample;SERVER=test;" & _ "UID=Postgres;PWD=;PORT=5432;"" На этом можно было бы закончить, но нельзя не упомянуть, что у некоторых ODBC драйверов есть одна замечательная особенность: они позволяют подключать таблицы вообще без создания DSN. В их числе драйверы для MS SQL Server 7.0 и PostgreSQL. Для этого надо просто вместо параметра DSN указать параметр DRIVER и имя драйвера, заключенное в фигурные скобки. Конечно, в таком случае потребуется указать все необходимые драйверу опции. Например: NewTableDef.Connect = "ODBC;DRIVER={PostgreSQL};DATABASE=sample;SERVER=test;" & _ "UID=Postgres;PWD=;PORT=5432;A6=;A7=100;" & _ "C2=dd_;CX=188373ab;A8=4096;B0=254;B1=8190;BI=8;" Опций может быть довольно много и это вызывает очень серьёзную проблему: длина строки подключения не может превышать приблизительно 270 символов. Разработчики драйвера PostgreSQL это понимают и пытаются найти выход путём кодирования некоторых опций. Параметр CX и является таким кодом. Формируется он так: первые два байта содержат количество реально значимых битов в последующем числе (в шестнадцатиричном формате). Например, 18 означает, что используются 24 бита которые представляют следующие опции драйвера: -- Младший бит -- LF <-> CR/LF conversion Updatable Cursors Disallow Premature Recognize Unique Index PROTOCOL 6.3 PROTOCOL 7.X,6.4 Unknown Sizes(Don't know) Unknown Sizes(Maximum) Disable Genetic Optimizer KSQO CommLog MyLog Parse Statements Cancel As FreeStmt Use Declare/Fetch Read Only Text As LongVarChar Unknowns As LongVarChar Bools As Char Row Versioning Show System Tables Oid Options(Show Column) Oid Options(Fake Index) True is -1 -- Старший бит -- Некоторые параметры невозможно закодировать таким образом и для их именования продолжают использовать буквоцифровые сокращения: Connect Settings A6 Cache Size A7 Socket A8 Max Varchar B0 Max LongVarChar B1 SysTable Prefixes C2 Int8 As BI Пример, который я сделал для Access'97, можно взять здесь. Он основан на подходе, описанном в заметке «Программное подключение таблиц из внешней базы данных MS Access», но содержит дополнительную таблицу, в которой хранится информация, необходимая для подключения к серверу. Так как сам подход достаточно универсален, пример годится для подключения не только к серверу PostgreSQL, но и к любому другому, возможно, с какими-нибудь незначительными доработками. Строку подключения можно легко получить, присоединив таблицу вручную, а затем скопировав всё содержимое свойства «Описание» (кроме тега table=...) из свойств таблицы, открытой в режиме конструктора. Для сервера PostgreSQL можно воспользоваться надстройкой, которую я создал специально для формирования строк коннекта и минимального администрирования сервера. |