Я прочитал атрибут pwdLastSet из Active Directory и хочу сохранить его в столбце DATETIME2(0) в таблице SQL Server. Я не хочу хранить доли секунды.
Это 8-байтовое целое число, выраженное с шагом 100 наносекунд с 12:00 AM, 1 января 1601. Я использую эта функция, чтобы преобразовать его в переменную Date.
Это продолжало терпеть неудачу с ODBC-call failed, и мне потребовалось некоторое время, чтобы понять, что дополнительная точность, возвращаемая этой функцией, вызвала ошибку.
Как лучше всего убрать доли секунды из переменной Date?
Я использую SQL Server 2008 R2 и Access 2010.
В SQL Server:
CREATE TABLE TestDT (
ID INT NOT NULL,
colDT2 DATETIME2(0) NULL,
CONSTRAINT PK_TestDT PRIMARY KEY (ID)
)
GO
INSERT TestDT (ID) VALUES (1)
GO
Свяжите эту таблицу с Access, используя драйвер ODBC для собственного клиента или текущий Драйвер Microsoft ODBC 17 для SQL Server. Драйвер SQL Server по умолчанию на самом деле не знает, как работать с DATETIME2.
В Access VBA:
Public Sub TestDT()
Dim DB As DAO.Database
Dim RS As DAO.Recordset
Dim dte As Date
Dim i As Long
Set DB = CurrentDb
' Random date+time
dte = CDate("2018-12-24 15:16:17")
' 1st iteration: write original date+time -> works
' 2nd iteration: try to write date+time with fractional seconds -> error for DATETIME2(0) column
For i = 1 To 2
If i = 2 Then
' Introduce milliseconds nastiness
dte = dte + 0.00001
End If
Debug.Print "Iteration " & i, Format(dte, "yyyy-mm-dd hh:nn:ss")
Set RS = DB.OpenRecordset("SELECT * FROM TestDT WHERE ID = 1", dbOpenDynaset)
With RS
.Edit
!colDT2 = dte
On Error Resume Next
.Update
If Err.Number <> 0 Then
Debug.Print "Error " & Err.Number, Err.Description
' The DAO Errors collection shows the actual error
Debug.Print Errors(0).Description
Else
Debug.Print "Update OK"
End If
On Error GoTo 0
.Close
End With
Next i
End Sub
Вывод:
Iteration 1 2018-12-24 15:16:17
Update OK
Iteration 2 2018-12-24 15:16:18
Error 3146 ODBC-Aufruf fehlgeschlagen.
[Microsoft][ODBC Driver 17 for SQL Server]Datetime field overflow.
Fractional second precision exceeds the scale specified in the parameter binding.
Хм, интересно. Нет, завтра попробую. @krishKM
Да, это тоже работает (правда, это "hh:nn:ss"). Спасибо!
если mm используется после hh, он делает то, что делает nn :)
Ого, еще какое-то безумие с датой и временем. Ты прав. : o @krishKM





Я придумал
dte = CDate(Int(dte) + TimeSerial(Hour(dte), Minute(dte), Second(dte)))
но это довольно коряво. :(
Вы можете округлить до второго следующим образом:
PwdLastSetSecond = CDate(Int(PwdLastSet * 86400) / 86400)
Магическое число 86400 заслуживает пояснительного комментария IMO или, что еще лучше, именованной константы, например Const SecondsPerDay = 86400
Это определенно менее неуклюже! :)
Правильная функция в Access для выделения временной части:
DateValue (выражение «дата / время»)
Таким образом, вы получаете:
dte = DateValue (CDate ("2018-12-24 15:16:17"))
или DateValue (любое выражение даты и времени)
Правильная функция в Access для выделения временной части:
TimeValue (выражение «дата / время»)
Таким образом, вы получаете:
dte = TimeValue (CDate ("2018-12-24 15:16:17"))
или TimeValue (любое выражение даты / времени)
Если вам нужно сохранить или выделить временную часть в отдельное значение, перейдите:
dtMyTime = TimeValue ((CDate ("2018-12-24 15:16:17"))
Однако ВАША ПРОБЛЕМА НЕ убирает дату или время.
НЕТ ТАКОГО «.ms» для формата.
Это даст вам месяц + секунды.
Если присмотреться:
2018-12-24 15: 16: 17.1217
Выше te 1217 - это 12-й месяц и 17 секунд.
НЕТ ТАКОГО «мс» для формата. Вот почему вы видите переполнение.
Таким образом, вы НЕ МОЖЕТЕ ИСПОЛЬЗОВАТЬ «.ms».
Вы можете получить только секунды в Access.
Просто используйте команду стандартного формата. Если вы хотите убрать «лишнее» время:
Set rst = CurrentDb.OpenRecordset("dbo_TimeTest2", dbOpenDynaset, dbSeeChanges)
rst.Edit
rst!StartTimeD = Format(rst!StartTimeD, "MM-DD-YYYY hh:nn:ss")
rst.Update
ОПАСНО ОПАСНО будет Робинзон. Access не использует и не поддерживает «ms» в формате.
Простое использование указанного выше «формата» для существующей даты / времени, которые вы получите, вытащит и выбросит лишние значения через секунды.
Вы совершенно правы в том, что .ms - это ерунда, я читал этот здесь, но не проверял и даже не читал этот поток до конца ... Но это не причина переполнения. - Назначение выражения Format(.., "MM-DD-YYYY hh:nn:ss") работает для удаления дробей.
Но @Andre, обратите внимание, что он округлит субсекундную часть на 4/5 - до ближайшего целого числа секунд. Это не округление доли секунды. Ни один из методов не является неправильным; что выбрать, зависит от контекста.
Это наверняка меня одурачило. Я никогда не видел ".ms" в этом формате, но подсказка заключалась в том, что "месяц" и "секунды" выглядели одинаково. Все в порядке, поскольку формат удаляет лишнюю десятичную информацию, содержащуюся в форматах sql datetime2. Они не должны влезать в картину, но если данные исходят не из Access, эта информация не может быть использована Access. Если исключить (игнорировать) эту информацию, то проблем нет. Если эта дополнительная информация необходима, тогда это вызов или проблема.
Интересно, пробовали ли вы
!colDT2 = format(dte, "yyyy-mm-dd hh:mm:ss")