SQL Server中datetime/datetimeoffset字段无法修改,默认取当前时间
看来你碰到了两个挺让人头疼的SQL Server时间字段更新问题,我来帮你一步步排查解决:
默认值为GETDATE()的DATETIME字段,正常来说默认约束只在插入新行时生效,更新操作不会被默认约束干扰。如果更新后字段值还是当前时间,大概率是这些原因:
检查是否存在AFTER UPDATE触发器
很多时候是表上的触发器在你更新后,又把字段值重置成了当前时间。你可以用这条SQL查询表上的触发器:SELECT name, definition FROM sys.triggers WHERE parent_id = OBJECT_ID('你的表名');如果查到触发器,看看它的定义里是不是有类似
SET 你的日期字段 = GETDATE()的逻辑,要是有的话,要么修改触发器逻辑,要么临时禁用触发器再执行更新(注意禁用触发器要谨慎,确保不会影响其他业务)。确认你的更新语句是否正确
别小看这个,有时候可能是列名写错、WHERE条件没命中目标行,或者值的格式不对。正确的更新语句应该是这样的:UPDATE 你的表名 SET 日期字段 = '2023-10-01 14:30:00' -- 用合法的DATETIME格式 WHERE 主键列 = 123; -- 确保WHERE条件能匹配到要更新的行执行完后可以加个
SELECT语句验证是否真的更新成功了。
这个问题的排查思路和第一个类似,但还要注意datetimeoffset类型的特性:
优先排查触发器和计算列
同样先查有没有AFTER UPDATE触发器自动把字段设为SYSDATETIMEOFFSET();另外还要确认这个datetimeoffset列是不是计算列——如果是计算列,它的值是自动计算的,你手动更新也不会生效。查询计算列的SQL:SELECT name, is_computed, computed_definition FROM sys.columns WHERE object_id = OBJECT_ID('你的表名') AND name = '你的datetimeoffset列名';如果
is_computed为1,那你得修改表结构,把计算列改成普通列才能手动更新。确保更新值的格式正确
datetimeoffset类型需要包含时区偏移信息,比如你要设置2015年的时间,得写成这样:UPDATE 你的表名 SET 偏移日期列 = '2015-06-15 09:00:00 +08:00' -- 明确时区偏移 WHERE 主键列 = 456;如果只写日期时间不写偏移,SQL Server会用服务器的默认时区补全,但也可能导致意想不到的问题,所以最好明确指定偏移量。
验证更新是否真的没生效
有时候可能是你查询的时候没注意时区转换,看起来像是当前时间,实际已经更新成功了。可以用CONVERT函数把datetimeoffset转成你熟悉的格式查看:SELECT CONVERT(VARCHAR(30), 偏移日期列, 127) AS 带偏移的时间 FROM 你的表名 WHERE 主键列 = 456;
内容的提问来源于stack exchange,提问作者Aftab Lala

