Укажите файл mdw во встроенной строке подключения к другому Jet mdb: возможно? - PullRequest
1 голос
/ 14 мая 2009

Я могу использовать следующий синтаксис в запросе Jet (mdb) для выбора данных из другого файла .mdb:

SELECT * FROM [Database=C:\Tempo\AnotherDB.mdb;].MyTable

альтернативно

SELECT * FROM MyTable IN 'C:\Tempo\Another.mdb'

Я хочу расширить это, чтобы использовать безопасность рабочей группы a.k.a. Безопасность на уровне пользователя (ULS). Я знаю, как указать идентификатор пользователя и пароль, например,

SELECT *
FROM
[Database=C:\Tempo\AnotherDB.mdb;UID=Admin;PWD=***;].MyTable

но это работает только тогда, когда оба mdb совместно используют один и тот же mdw.

Как бы я указал путь к файлу mdw, используемому для защиты другого mdb? Является ли это возможным? Если нет, то почему?

P.S. Я задал этот вопрос много лет назад в этом сообщении группы новостей Access , но не получил ответа. Я сдался после того, как Access MVP убедил меня, что это невозможно; Я не помню деталей, но это было как-то связано с базовой архитектурой (рабочее пространство поддерживает только один файл рабочей группы, и для запроса Jet отсутствует механизм создания нового рабочего пространства - что-то подобное)

Мой возобновленный интерес вызван этим SO комментарием .

Ответы [ 5 ]

2 голосов
/ 18 мая 2009

Короткий ответ - нет. Если вы используете исходную базу данных, вы не сможете указать другую рабочую группу, а если оставить ее пустой и указать допустимую строку подключения, вы получите ошибку ISAM. (Хотя этот метод отлично работает для других баз данных, таких как SQL Server.) Пример (не работает):

SELECT *
FROM Table1 IN '' [Provider=Microsoft.Jet.OLEDB.4.0;Password=foo;User ID=Oorang;Data Source=C:\Users\Oorang\Documents\db1.mdb;Persist Security Info=True;Jet OLEDB:System database=C:\Users\Oorang\Documents\Security.mdw];

Однако вы можете сделать это с помощью ADO. Я не уверен, что вы пытаетесь выполнить, как только у вас есть запрос, но вот как получить его в наборе записей:

Option Explicit
Sub ADODBExample()
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Set cn = New ADODB.Connection
    cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Password=foo;User ID=Oorang;Data Source=C:\Users\Oorang\Documents\db1.mdb;Persist Security Info=True;Jet OLEDB:System database=C:\Users\Oorang\Documents\Security.mdw"
    Set rs = New ADODB.Recordset
    rs.Open "SELECT * FROM Table1;", cn
    Debug.Print rs.GetString
    rs.Close
    cn.Close
End Sub

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

1 голос
/ 16 октября 2009

Простой ответ: это невозможно.

0 голосов
/ 19 августа 2013

Пользовательскую функцию можно использовать для ЧТЕНИЯ данных из другой рабочей группы при использовании ДОСТУП .

Ограничение доступа связано с тем, что только в Access есть хуки VB, которые позволяют вам использовать пользовательские функции. Это эквивалентно использованию пользовательских функций SQL-сервера, которые запускаются только при наличии SQL Server.

Ограничение только для чтения связано с тем, что Access не предоставляет хуки для пользовательских переменных, только пользовательские функции.

В Access, в пользовательской функции, вы помещаете код так:

Dim dbe As DAO.DBEngine
Dim ws As DAO.Workspace
Dim db as DAO.database

    Set dbe = New DAO.PrivDBEngine
    dbe.SystemDB = "whatever.mdw"
    dbe.DefaultUser = "whatever"
    dbe.DefaultPassword = "whatever"

    Set ws = dbe.Workspaces(0)
    Set db = ws.opendatabase( ... )

В этом UDF вы можете использовать это рабочее пространство для чтения данных из другой базы данных, используя файл рабочей группы «что угодно».

Примечание: если вы вызываете это из запроса select, сделайте dbe и ws и db и rs глобальными, чтобы не открывать файлы каждый раз, когда вы касаетесь поля в записи. Тогда функция просто имеет

if rs is empty then
   set dbe = ...
   ...
   set rs = db.openrecordset(...)
end if 
...

Примечание. Если вы действительно этого хотите, вы можете поместить запрос на обновление в udf, вызываемый из оператора select. Сделайте это, если вы надеетесь увидеть его на thedailywtf.com позже.

PS: это необычное решение. Я был где-то в 2004 году, но вы бы этого не получили, отправив сообщение на «Gettingstarted»

0 голосов
/ 20 мая 2009

Может быть, мне следует объединить и уточнить :) В контексте вашего исходного вопроса ответ таков: Вы не можете сделать это через SQL / Query Builder, если базы данных: и Access, и имеют разные mdw. Однако , если обе базы данных являются Access и имеют одинаковое mdw (как указано в вашем последующем комментарии), то вы можете сделать это через SQL / Query Builder. В этом конкретном сценарии вы бы не (не могли) сделать это через строку подключения, вы бы сделали это, выполнив шаги 1-4 ниже, а затем замените шаг 5a на 5b.

Если базы данных имеют и Access, и разные mdw , то единственный способ указать другую рабочую группу - использовать строку подключения. Однако SQL / Query Builder выдаст ошибку ISAM, если вы попытаетесь через свойство строки соединения (на шаге 5a ниже). Таким образом, вы не можете сделать это через построитель запросов. Вы можете сделать это с VBA, используя ADO, как в моем примере, опубликованном ранее.

Помните, что свойство строки подключения в построителе запросов предназначено для не -Access баз данных, исходная база данных для баз данных Access с таким же (или нет) mdw. Для баз данных Access с различными mdws единственным известным мне решением является VBA, которое я выложил ранее.

Теперь об использовании строки подключения непосредственно в SQL. Вы можете сделать это. Но есть некоторые предостережения: он не будет работать с другими базами данных Access. Если вы сделаете это с таблицами dbo SQL Sever, вам придется отредактировать SQL, сгенерированный построителем запросов, чтобы удалить «dbo». Приставка.

Я думаю, что самый простой способ - просто провести вас через то, что я пытаюсь сказать.

  1. Установите рабочую строку соединения для базы данных без доступа . (Я предлагаю, чтобы было проще, просто используйте файл Excel.)
  2. Когда у вас есть строка, откройте построитель запросов в Access.
  3. Закрыть диалоговое окно выбора таблицы.
  4. Нажмите Alt-Enter, чтобы открыть Query Properties. 5а. В «Source Connect Str» вставьте строку подключения. * 5b. Вставьте путь к другой базе данных в «Исходной базе данных».
  5. Теперь добавьте свои таблицы и создайте запрос.
  6. Перейти к представлению SQL. Посмотрите, что было построено.

Но этот подход практически не имеет значения, хотя он действителен для не -Access баз данных, не работает для Access . (Это немного расстраивает, я знаю.)

Пример используемой строки подключения:

SELECT [Sheet1$].F1
FROM [Sheet1$] IN '' [Excel 5.0;HDR=NO;IMEX=2;DATABASE=C:\Users\Oorang\Documents\Book1.xls];

Я действительно не думаю, что это действительно ACE / Jet синтаксис для установки OLE DB Строка подключения в базу данных IN пункт.

Точно так же, как к вашему сведению, вы используете строку подключения, как показано выше, но если вы используете свойство Source Db, вы получите то, что ниже :) (Я протестировал все свои примеры перед тем, как опубликовать их:))

SELECT *
FROM Table1 IN 'C:\Users\Oorang\Documents\db2.mdb';
0 голосов
/ 19 мая 2009

Ну ... на самом деле вы можете использовать строку подключения. Лучше всего работает с SQL Server. Я просто показывал, как бы он хотел работать с Access. Я пытался подчеркнуть, что существует правильный синтаксис ... Просто Access не позволит вам сделать это с помощью Access. (Это позволит позволить вам сделать это, если соединение с базой данных другого типа.) Забавно, что эта функция совместима с другими типами БД, а не с Access ... Когда это Access Но, тем не менее, правда.

Хотя, если они защищены одним и тем же MDW, все, что вам нужно сделать, это сделать, и запрос будет выполняться в контексте текущего пользователя:

SELECT *
FROM Table1 IN 'C:\Users\Oorang\Documents\db2.mdb';
...