使用 T-SQL 转换 AD 时间戳

问题描述 投票:0回答:3

如何将 Windows NT 时间从 SQL 查询拉取转换为可读格式? 我正在对用户帐户进行 AD 拉取,我想将 Windows AD 时间戳转换或转换为更好的可读格式。问题是我在拉动时遇到转换问题。

查询:

SELECT
  CASE
    WHEN CHARINDEX('@', userPrincipalName) > 7
      THEN SUBSTRING(userPrincipalName, 1, (CHARINDEX('@', userPrincipalName)) - 1)
    ELSE ''
  END AS edipi
 ,UPPER(samaccountname) AS samaccountname
 ,givenName AS firstName
 ,sn AS lastName
 ,initials
 ,UPPER(mail) AS email
 ,userAccountControl
 ,telephoneNumber
 ,title
 ,accountExpires
FROM
  OPENQUERY
    (ADSI
     ,'select 
          givenName, 
          samaccountName, 
          userPrincipalName, 
          sn, 
          initials, 
          mail, 
          userAccountControl, 
          telephoneNumber, 
          title, 
          accountExpires
        from ''LDAP PATH''
        where objectcategory=''person'' and objectclass = ''user'' and name=''*'' '
    );

我的查询返回 Windows NT 时间的 accountExpires 字段,但是,我希望它是这样的:

2020-02-09 15:23:36.367

而不是这个:

132257354163700000

我想出了一个简单的解决方案来进行逐一转换,但我希望它在拉动时进行 CAST,而不是必须为每个用户执行此操作

DECLARE @accountExpired BIGINT
SET @accountExpired = 132257354163700000; --This is a random time pulled from a user from the above select statement.

SELECT CAST((@accountExpired / 864000000000.0 - 109207) AS DATETIME);
sql sql-server tsql
3个回答
3
投票

当 SQL Server 执行从 nvarchar

numeric
(或实际上从
anything
numeric)的
隐式转换
时,它将默认精度和小数位数设置为
numeric(18,0)
。这对于您问题中的示例数据来说已经足够了,但是错误消息表明您的数据集中的某个值超出了默认数据类型的容量。

要克服这个问题,请尝试显式转换为更大的容量

numeric
。也许:

SELECT
  ...
 ,CAST((CAST(accountExpires AS numeric(28,0)) / 864000000000.0 - 109207) AS DATETIME)
 ...

可能,

numeric(19,0)
就足够了,但如果您超过 19,您最好选择 28,因为 20-28 都具有相同的存储大小。


1
投票

这对我来说对 AD 中的每个用户都有效。

CAST((convert(bigint, lastlogontimestamp) / 864000000000.0 - 109207) AS DATETIME) as lastLogonTimestamp,

-- 克服日期时间转换为大或小为空的限制 当convert(bigint, accountexpires) = 0然后为空时的情况 当转换(bigint,帐户过期)> 2650467743999999716 然后 null else CAST((convert(bigint, accountexpires) / 864000000000.0 - 109207) AS DATETIME) 结束为 accountexpires


0
投票

晚了几年,但希望这可以帮助其他尝试查询 LDAP 的人。

Erics 的回答很棒!但是,我遇到了溢出错误,不得不将 NUMERIC(28,0) 增加到 NUMERIC(38,0) 以考虑来自 AD 的非常大的数字/日期。 下面的 Select 语句示例将输出“2023-07-15 00:00:00.000”

select CAST((CAST(133338528000000000 AS numeric(38,0)) / 864000000000.0 - 109207) AS DATETIME) as accountExpires

下面是一个工作示例,当然是在我的域上,它从 LDAP 中提取 500 条记录并将 accountExpires 转换为可读日期。 userAccountControl 语句仅用于拉动活跃和禁用员工,并排除没有密码的帐户。

 SELECT TOP 500 [name], adsPath, streetaddress, pager, company, title, displayName, telephoneNumber, sAMAccountName, mail, mobile,facsimileTelephoneNumber, department, physicalDeliveryOfficeName, givenName, cn, initials, mailnickname, othertelephone,ou, postaladdress, l, postalcode, st, C, sn, Manager, userPrincipalName,distinguishedName, userAccountControl,employeeID
,CAST((CAST(accountExpires AS numeric(38,0)) / 864000000000.0 - 109207) AS DATETIME) as accountExpires
FROM OPENQUERY(ADSI,
'<LDAP://MyDomain.com/DC=MyDomain,DC=com>;
(&(employeeNumber=*)(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=512)(!userAccountControl:1.2.840.113556.1.4.803:=32)(userAccountControl:1.2.840.113556.1.4.803:=2)(samAccountType=805306368)(mail=*)(uSNChanged=*));
name,adsPath,streetaddress,pager,company,title,displayName,telephoneNumber,sAMAccountName,mail,mobile
,facsimileTelephoneNumber,department,physicalDeliveryOfficeName,givenName,cn,initials,mailnickname, othertelephone
,ou,postaladdress,l,postalcode,st,C,sn,Manager,userPrincipalName, distinguishedName, userAccountControl,employeeID,accountExpires;subtree')

我希望这有帮助

© www.soinside.com 2019 - 2024. All rights reserved.