#sql-server #ms-access
#sql-сервер #ms-access
Вопрос:
Я переношу интерфейсное / серверное приложение MS Access на серверный интерфейс MS Access / sql server.
Одна часть этого приложения (в оригинальной форме) использует VB для импорта CSV-файла в таблицу во внешнем интерфейсе, а затем выполняет различные инструкции SQL для объединения содержимого этой таблицы в некоторые внутренние таблицы.
Я полагаю, что в новой среде, поскольку более эффективно выполнять процесс слияния в хранимой процедуре, моя стратегия должна быть
- Откройте соединение с серверной частью
- Создайте временную таблицу в этом соединении
- Создайте tabledef в VB и попытайтесь подключить его к этой временной таблице
- Используйте DoCmd.TransferText (как я делаю в оригинале) для импорта CSV-файла в таблицу, на которую ссылается таблица def
- Выполните хранимую процедуру в открытом соединении, которая объединяет данные временной таблицы с постоянными таблицами на серверной части.
Я думаю, что успешно выполняю шаги 1 и 2, но я не уверен. Я могу видеть временную таблицу в SQL Server Management Studio, но попытка открыть столбцы завершается ошибкой (она также завершается с той же ошибкой, когда я использую Management Studio для создания временной таблицы, поэтому я думаю, что это проблема Management Studio).
Я использую тот же код для выполнения шага 3, который я использую для связывания во всех постоянных таблицах при запуске приложения, но этот бит не работает. Наконец, я доказал, что шаг 5 работает, запустив его для невременной таблицы.
Код, который я использую для этого, выглядит следующим образом
Set conn = New ADODB.Connection
conn.Open getStrConn
'First create a temporary table on the server for the web site leads
SQL = "CREATE TABLE [dbo].[#WebSiteLeads]("
SQL = SQL amp; "[leadID] [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED,[Title] [nvarchar](255) NULL,[Firstname] [nvarchar](50) NULL,"
SQL = SQL amp; "[Lastname] [nvarchar](50) NULL,[Sex] [nvarchar](10) NULL,[House] [nvarchar](50) NULL,"
SQL = SQL amp; "[Address1] [nvarchar](50) NULL,[Address2] [nvarchar](50) NULL,[Street] [nvarchar](50) NULL,"
SQL = SQL amp; "[Town_City] [nvarchar](50) NULL,[County] [nvarchar](50) NULL,[Postcode] [nvarchar](10) NULL,"
SQL = SQL amp; "[Email] [nvarchar](50) NULL,[Allow_email] [nvarchar](5) NULL,[Telephone] [nvarchar](20) NULL,"
SQL = SQL amp; "[Allow_tel] [nvarchar](5) NULL,[Cons_period] [nvarchar](20) NULL,[When] [nvarchar](20) NULL,"
SQL = SQL amp; "[Procedure] [nvarchar](20) NULL,[Consultation] [nvarchar](10) NULL,[Info_pack] [nvarchar](10) NULL,"
SQL = SQL amp; "[Source] [nvarchar](20) NULL,[Further_info] [nvarchar](255) NULL,[Callback] [nvarchar](50) NULL,"
SQL = SQL amp; "[Date_added] [nvarchar](30) NULL,[Date_added_dt] [datetime] NULL,[Callback_range] [tinyint] NULL,"
SQL = SQL amp; "[UcFname] [nvarchar](1) NULL,[UcLname] [nvarchar](50) NULL,[UcPcode] [nvarchar](10) NULL);"
conn.Execute SQL
For Each td In CurrentDb.TableDefs
If td.name = "WebsiteLeads" Then
CurrentDb.TableDefs.Delete "WebsiteLeads"
End If
Next
'link to the table just created
Set td = CurrentDb.CreateTableDef("WebsiteLeads",dbAttachSavePWD , "[dbo].[#WebSiteLeads]", getStrConn)
CurrentDb.TableDefs.Append td
importProgress = 0.1 'Update Progress bar
DoEvents
'Import our text file
DoCmd.TransferText acImportDelim, "Leads Import v2", "WebsiteLeads", txtFileName
importProgress = 0.3 'Update Progress bar
DoEvents
'We are going to do the rest as Access stored procedure
Set leadsRS = conn.Execute("EXEC dbo.LeadsImport;")
importProgress = 0.9 'Update Progress bar
DoEvents
Но это не удается на
CurrentDb.TableDefs.Append td
с сообщением об ошибке «Не удалось найти устанавливаемый ISAM».
Что это за сообщение об ошибке и почему я его получаю
Комментарии:
1. Обязательно ли это должна быть временная таблица на SQL Server? Мне кажется, вы каждый раз создаете temp с одной и той же структурой. Вы могли бы просто очищать ее при каждом запуске sp. Вы можете связать с обычной таблицей SQL Server просто отлично, не так ли?
2. Я думаю, вы застряли. Я не знаю ни о каком способе ссылки на временную таблицу. Однако в предыдущем комментарии у HansUp есть хороший обходной путь — создайте постоянную таблицу (структуру) в SQL Server и обработайте ее содержимое как временное, заставив SP обрезать его непосредственно перед импортом (если ваш администратор базы данных не предоставит вам разрешения, необходимые для усечения, вам придется довольствоваться удалением).
3. Я нашел способ обойти проблему — я думаю. Основная причина, по которой я использовал временную таблицу, заключается в том, что если два пользователя импортируют одновременно, они могут споткнуться друг о друга. Временная таблица эффективно предоставляет отдельное пространство имен каждому пользователю. Но если я оберну все это в транзакцию begin .. commit, я могу получить это разделение с помощью процессов транзакции
4. Я забыл в приведенном выше сказать, что таблица, которую я использую, может быть постоянной, как предложил ХансУп.
5. Рассматривали ли вы возможность создания временной таблицы локально, на рабочей станции, и использования Jet / ACE MDB / ACCDB, хранящейся на рабочей станции, для временной таблицы? В этом случае имя таблицы всегда будет одинаковым, но оно всегда будет специфичным для каждого пользователя.
Ответ №1:
Другой альтернативой было бы вообще не использовать связанную таблицу, а вместо этого использовать сквозной запрос, который возвращает временную таблицу. Скорее всего, вам придется писать это на лету, но как только он вернет правильную временную таблицу, ее можно использовать в качестве источника записи формы или отчета.
Я нередко создавал сохраненные запросы, которые заменяют связанные таблицы, хотя я никогда не делал этого с помощью сквозного подключения к временной таблице.
Комментарии:
1. Интересно — хотя я не уверен, что это сработает — камнем преткновения является DoCmd. TransferText, для которого требуется имя таблицы. Из ссылки «Строковое выражение, являющееся именем таблицы Microsoft Access, в которую вы хотите импортировать текстовые данные, экспортировать текстовые данные или связать текстовые данные с запросом Microsoft Access, результаты которого вы хотите экспортировать в текстовый файл». который разрешает запрос только при экспорте. Я нашел обходной путь (см. Комментарий выше), поэтому использую его. Позже сегодня я буду изучать сквозные запросы путем динамического создания querydef, вызывающего хранимую процедуру
2. Если вы пишете сохраненный запрос, DoCmd. TransferText вообще не используется. В этом вся моя суть — вы полностью избегаете проблемы. Короче говоря, вы, кажется, пропустили весь смысл моего ответа.
3. Я либо что-то упускаю, либо, возможно, вы не совсем понимаете, что я делаю. DoCmd. TransferText передает, используя спецификацию во внешнем интерфейсе, файл CSV, загруженный локально на компьютере, на котором запущен внешний интерфейс, в таблицу, о которой мы говорим. Если я не попытаюсь проанализировать этот файл программно, TransferText кажется единственным способом загрузить его в таблицу.
4. И я хочу сказать, что ВАМ НЕ НУЖНА ТАБЛИЦА — запрос может выполнить эту работу (ПРЕДСТАВЛЕНИЕ). Вы можете написать QueryDef «на лету» по мере необходимости, и вам не нужно беспокоиться о наличии постоянной связанной таблицы. Единственная причина, по которой вам нужно сохранить QueryDef (в отличие от назначения SQL SELECT в качестве источника записей / источника строк объекту Access), заключается в том, что вам нужно использовать сквозной переход, чтобы иметь полный доступ к временным таблицам.
5. ! Загорается индикатор — я понимаю, что вы сейчас говорите! Извините, я был тупым. Я только что создал пассивный запрос для другой части приложения, которая вызывает хранимую процедуру для использования в качестве источника данных для отчета. Пришлось немного повозиться, чтобы перейти от соединения ADO к DAO. QueryDef (см. chandlerfamily.org.uk/2011/05 / … )