一些背景知识:
我目前正在使用SQL Server数据库驱动的应用程序,该应用程序包含审计表,这些表根据用户执行的某些操作自动更新。我们有一个功能请求,以DateTime
的形式向这些审计表添加其他信息。问题在于,所需日期时间对象的源数据仅存在于两个字符串值(一个用于日期,一个用于时间),这些值存储在“对象属性”表中(我们无法修改,因为它形成键值对形式的软件堆栈的核心部分。包含信息的“属性表”看起来有点像这样:
| Foreign_Key (uniqueidentifier) | Data_Key (nvarchar) | Data_Value (nvarchar) |
| {guid 1} | 'Date' | '10/11/12' |
| {guid 1} | 'Time' | '1315' |
| {guid 2} | 'Date' | '11/12/13' |
| {guid 2} | 'Time' | '1416' |
我们要尝试实现的是根据上述数据将纯DateTime
值插入审计表(出于此问题的目的,我们可以修改)。理想的输出是:
| Primary_Key (uniqueidentifier) | DateT_Value (datetime) |
| {guid 1} | 10/11/12 13:15:00 |
| {guid 2} | 11/12/13 14:16:00 |
为了强制执行此操作,我为源表编写了以下SQL Server触发器,根据相关对象的ID,该表应根据存储在属性表中的两个字符串值创建DateTime
值。 :
DECLARE @DateFormat INT
SET @DateFormat = -- Subquery to retrieve date format ID - removed for clarity
UPDATE AuditTable
SET DateT_Value =
DATEADD (minute,
(CONVERT(INT, SUBSTRING(
(SELECT Data_Value
FROM inserted
WHERE inserted.Data_Key = 'Time'
AND inserted.Foreign_Key = AuditTable.Primary_Key)
, 3, 2)) + ((CONVERT(INT, SUBSTRING(
(SELECT Data_Value
FROM inserted
WHERE inserted.Data_Key = 'Time'
AND inserted.Foreign_Key = AuditTable.Primary_Key),
1, 2))) * 60)),
CONVERT(DATETIME,
(SELECT Data_Value
FROM inserted
WHERE inserted.Data_Key = 'Date'
AND inserted.Foreign_Key = AuditTable.Primary_Key),
@DateFormat))
FROM AuditTable
INNER JOIN inserted
ON inserted.Foreign_Key = AuditTable.Primary_Key
现在,当我尝试独立运行此查询时(删除对'inserted'的引用并将内存表替换为它将引用的实际表的实例),它工作正常 - DateT_Value字段将按预期为审计表中的所有行填充。
然而,当这个逻辑放在一个触发器中并且我试图使用'inserted'表(理论上它应该包含所有被添加到'source'表中的行)时,我得到一个NULL值被插入'audit'表的DateTime字段。
我只能假设无论出于何种原因,'inserted'表都不会将任何行返回到外部更新语句 - 但是假设我基于ID(已知是唯一的)和字段名称加入转换逻辑中的源表(在这种情况下,它永远不会包含特定字段的多个数据实例)我会认为这样就足够了吗?
值得注意的是,我尝试从触发器中删除复杂的日期转换逻辑并将其替换为简单的
UPDATE AuditTable
SET DateValue = GETDATE() -- Fake date
FROM AuditTable
INNER JOIN inserted
ON inserted.Foreign_Key = AuditTable.Primary_Key
用于调试目的 - 但我仍然看到相同的行为。
我遗漏了'inserted'表的行为吗?
干杯。
答案 0 :(得分:0)
关于时间安排。当您使用触发器时,它尚未反映到db。在该事务中,您尝试获取值并尝试加入,但尚未在触发器中创建该值。拆分查询,首先插入,然后更新