MS Access: формат даты для SQL-вставки с использованием VBA

Вопрос: Это может быть очень простой вопрос, но мне трудно понять информацию, которую я нашел в Интернете до сих пор. Когда я пытаюсь запустить SQl из моего VBA, это дает мне несоответствие типа на моей strSQl. У меня есть таблица [tbl_DatabaseUpdateLog] с 4 столбцами UpdateID (Autonumber) Начало (дата/время) Конец (дата/время) Продолжительность (дата/время) Я должен регулярно

Вопрос:

Это может быть очень простой вопрос, но мне трудно понять информацию, которую я нашел в Интернете до сих пор. Когда я пытаюсь запустить SQl из моего VBA, это дает мне несоответствие типа на моей strSQl.

У меня есть таблица [tbl_DatabaseUpdateLog] с 4 столбцами

UpdateID (Autonumber)

Начало (дата/время)

Конец (дата/время)

Продолжительность (дата/время)

Я должен регулярно извлекать информацию из баз данных компании для меньшего проекта анализа, и я хочу регистрировать, как часто и сколько времени требуется для выполнения этих запросов. Каждый раз при запуске обновления выполняется следующее:

Dim StartUpdate, EndUpdate, LengthUpdate, strSQl As Date StartUpdate = Time() Call UpdateAll ‘This calls the collection of queries and is irrelevant for my problem EndUpdate = Time() LengthUpdate = EndUpdate — StartUpdate Forms!frm_Timer.Caption = «Update Completed at » & EndUpdate & » (» & Format(LengthUpdate, «HH:MM:SS») & «)» DoCmd.SetWarnings (0) strSQl = «INSERT INTO tbl_DatabaseUpdateLog ( Start, [End], Duration ) » & _ «SELECT ‘» & StartUpdate & «‘ AS Started, ‘» & EndUpdate & «‘ AS Ended, ‘» & LengthUpdate & «‘ AS Lasted» DoCmd.RunSQL strSQl DoCmd.SetWarnings (-1) DoCmd.Close acForm, Me.Name

Я пробовал использовать # вокруг дат и использовать Now() вместо Time(), но я чувствую, что у меня отсутствует базовая концепция, которая поможет мне исправить эту проблему. Мне просто нужно Время дня и продолжительность (не столько сама дата), если это помогает.

Лучший ответ:

Когда я пытаюсь запустить SQl из моего VBA, это дает мне несоответствие типа на моем strSQl

Изучите эти 2 заявления…

Dim StartUpdate, EndUpdate, LengthUpdate, strSQl As Date strSQl = «INSERT INTO tbl_DatabaseUpdateLog ( Start, [End], Duration ) » & _ «SELECT ‘» & StartUpdate & «‘ AS Started, ‘» & EndUpdate & «‘ AS Ended, ‘» & LengthUpdate & «‘ AS Lasted»

Когда вы объявляете strSQl As Date, это означает, что strSQl может удерживать только значения даты/времени. Строка, такая как “INSERT INTO… whatever” не является значением Date/Time. Поэтому, когда вы strSQl сохранить такую строку в strSQl, Access жалуется, что типы данных несовместимы: “Тип несоответствия”.

Поскольку вы намерены strSQl хранить текст SQL-запроса, объявите его таким образом (вместо As Date): Dim strSQl As String

Это изменение приведет вас к ошибке. Для вашей более широкой цели используйте запрос параметров с DAO.

Dim db As DAO.Database Dim qdf As DAO.QueryDef Dim StartUpdate As Date, EndUpdate As Date, LengthUpdate As Date Dim strSQl As String StartUpdate = Time() Call UpdateAll ‘This calls the collection of queries and is irrelevant for my problem EndUpdate = Time() LengthUpdate = EndUpdate — StartUpdate Forms!frm_Timer.Caption = «Update Completed at » & EndUpdate & » (» & Format(LengthUpdate, «HH:MM:SS») & «)» strSQl = «INSERT INTO tbl_DatabaseUpdateLog ([Start], [End], Duration) » & _ «VALUES ([p1], [p2], [p3]);» Set db = CurrentDb Set qdf = db.CreateQueryDef(vbNullString, strSQl) With qdf .Parameters(«p1»).Value = StartUpdate .Parameters(«p2»).Value = EndUpdate .Parameters(«p3»).Value = LengthUpdate End With qdf.Execute dbFailOnError DoCmd.Close acForm, Me.Name

Обратите внимание, что при таком подходе для INSERT формат даты даже не является проблемой. Поскольку StartUpdate, EndUpdate и LengthUpdate будут действительными значениями Дата/Время, вы можете просто передать их параметрам, не беспокоясь о формате и # разделителях.

Ответ №1

Я вижу, что вы используете INSERT INTO SELECT FROM (literal) когда простой INSERT INTO (columns) VALUES (values) будет проще. Вы также можете иметь несколько VALUES в одном операторе INSERT, который является опрятным.

Я также вижу, что вы храните денормализованные данные, ясно, что Duration можно получить из End — Start, поэтому вы можете отказаться от этого столбца.

Кроме того, избегайте венгерской нотации, в этом случае префикс имени таблицы с помощью tbl_. Это не 80-е годы. Не делай этого.

Содержание

  1. Ужасный короткий и простой ответ с использованием конкатенации строк:
  2. SQL Server
  3. Доступ /Jet
  4. Лучший ответ: используйте параметры
  5. SQL Server
  6. Доступ /Jet

Ужасный короткий и простой ответ с использованием конкатенации строк:

(Никогда не делайте этого)

SQL Server

Если вы используете SQL Server, вам нужно заключать даты в одинарные кавычки, и вам необходимо преобразовать их в однозначную строку формата даты, например, yyyy-MM-dd HH:mm:ss.

strSQL = «INSERT INTO neverDoThis VALUES ( ‘» & Format( startUpdate, «yyyy-MM-dd HH:mm:ss» & «‘ )»

Доступ /Jet

Если вы используете Access или Jet, вам нужно заключить даты в хэш-символы “#” и использовать формат “MM/dd/yyyy hh: mm: ss tt” (тупые американцы…).

strSQL = «INSERT INTO neverDoThis VALUES ( #» & Format( startUpdate, «MM/dd/yyyy hh:mm:ss tt» & «# )»

Здесь ссылка для функции ” Format: https://msdn.microsoft.com/en-us/library/office/gg251755.aspx?f=255&MSPPError=-2147217396

Лучший ответ: используйте параметры

(Делайте это вместо этого)

SQL Server

SQL Server использует именованные параметры, такие как @foo:

cmd.CommandText = «INSERT INTO databaseUpdateLog ( [Start], [End], [Duration] ) VALUES ( @start, @end, @duration )» cmd.Parameters.Append cmd.CreateParameter( «@start», , , startUpdate ) cmd.Parameters.Append cmd.CreateParameter( «@end», , , endUpdate ) cmd.Parameters.Append cmd.CreateParameter( «@duration», , , lengthUpdate )

Доступ /Jet

Доступ использует анонимные заполнители, к которым обращается заказ, который они добавили, используйте ‘?’:

cmd.CommandText = «INSERT INTO databaseUpdateLog ( [Start], [End], [Duration] ) VALUES ( ?, ?, ? )» cmd.Parameters.Append cmd.CreateParameter( «?», , , startUpdate ) cmd.Parameters.Append cmd.CreateParameter( «?», , , endUpdate ) cmd.Parameters.Append cmd.CreateParameter( «?», , , lengthUpdate )

Метод Append в VBA является Sub поэтому его вызов не использует скобки.
CreateParameter метод имеет 3 необязательные аргументы в середине: Type, Direction и Size, которые могут быть выведены из значений, поэтому они опущены, положив ,, ,.

Ответ №2

Более прямой метод использует собственный DAO:

Dim rs As DAO.Recordset Dim StartUpdate As Date Dim EndUpdate As Date Dim LengthUpdate As Date StartUpdate = Time Call UpdateAll ‘This calls the collection of queries and is irrelevant for my problem. EndUpdate = Time LengthUpdate = EndUpdate — StartUpdate Forms!frm_Timer.Caption = «Update Completed at » & EndUpdate & » (» & Format(LengthUpdate, «h:mm:ss») & «)» Set rs = CurrentDb.OpenRecordset(«Select Top 1 * From tbl_DatabaseUpdateLog») rs.AddNew rs!Start.Value = StartUpdate rs!End.Value = EndUpdate rs!Duration.Value = LengthUpdate rs.Update rs.Close Set rs = Nothing DoCmd.Close acForm, Me.Name Ответ №3

Чтобы вычислить только время суток, в VBA вы можете использовать это выражение:

CDate(Now — Date())

Включите результат в #, так как результат все еще является типом даты, хотя сохраняется только информация о времени.

Вы можете использовать функцию DateDiff для вычисления продолжительности, вам нужно выбрать соответствующие единицы. например:

DateDiff(DateInterval.Second, EndUpdate, StartUpdate)

В результате получается длинное целое число, поэтому вам не нужно заключать результат в ваш SQL.

BTW, параметризующий ваш SQL, рекомендуется, но не требуется.

Оцените статью
Добавить комментарий