为什么我在 SQL Server 中插入一个空 DateTime 值时会得到 "0001-01-01"?

12

我试图在一个类型为“date”的字段中插入空值(DateTime)到我的数据库中,但我总是得到一个'0001-01-01'。我不明白为什么这个默认值会出现,因为这个字段允许为空。

我正在使用C# asp .net和MVC(Entity Framework),以下是我的代码:

Budget_Synthesis newBS = new Budget_Synthesis
{
    Budget_Code = newBudgetCode,
    Last_Modified_Date = null
};
db.Budget_Synthesis.AddObject(newBS);

Last_Modified_Date的类型是System.DateTime?,所以我不知道为什么他们改变了这个“null”。

如果我尝试在我的应用程序上显示该值,则会得到01/01/0001 00:00:00

而在SSMS中则是0001-01-01

有人能解释一下为什么我无法获得真正的“NULL”吗?

最好的问候


4
请展示你的代码。 - Ilya Ivanov
3
你是如何尝试插入的?这很重要。非常重要。 - Marc Gravell
4
SQL Server 无法存储0001-01-01;SQL Server 的最小值为1753年1月1日。你在哪里看到这个0001-01-01,确切地说? - Marc Gravell
@MarcGravell - 也许他指的是 datetime2 - Corak
2
关于最新的编辑:您展示了一些代码,将一个对象添加到某种ORM中。没错,我们正在接近答案……这是哪个ORM?那个AddObject是什么?这一切是如何配置的?您没有告诉我们有关所有这些如何到达数据库的任何信息... - Marc Gravell
显示剩余10条评论
6个回答

11

我认为这是对应于 null 的值。


5
@Andomar,这很好,但这并不是这个答案所说的。 - Marc Gravell
@MarcGravell:这条评论是额外的信息。如果你运行 var d = new DateTime(); Console.WriteLine(d);,它会打印出 0001-01-01,这让我不同意下票的观点。 - Andomar
1
@Andomar 是的,我非常清楚 datetime 的零行为;但是如果没有来自 OP 的更多上下文,这只是一个随机的小知识点。实际上,现在编辑到问题中的代码显示了对 null 的使用,这表明类型很可能是 DateTime?DateTime? 的默认值 不是 0001-01-01。 - Marc Gravell
1
@MarcGravell:是的,我想nHibernate、Linq2Sql或EF在某个地方将null转换为DateTime,最终变成了0001-01-01。也许在EF中该列被标记为非空。从某种意义上说,null对应于0001-01-01,这就是这个答案所说的。可能不是一个出色的答案,但它来自一个新用户,我认为这根本不值得被踩。 - Andomar

7
如果Last_Modified_DateDateTime类型,则无法有“真正的空”,因为DateTime结构 -正如其他人已经说过-不可为空。所以你的示例代码甚至不会编译。
如果Last_Modified_DateDateTime? (Nullable<DateTime>)类型,那么你的代码是正确的,但是-就像@Nikola Dimitroff在他的回答中所说的那样-你不能在数据库中有“真正的空”,因为DateTime?的默认值是01/01/0001 00:00:00。
你要寻找的“真正的空”是DBNull.Value,但是你只能用它来处理System.DBNull类型;如果你赋值Last_Modified_Date = DBNull.Value,无论Last_Modified_Date的类型是什么,你的代码都无法编译。

3

当你说你正在尝试放置一个空的DateTime时,你是使用Nullable<DateTime>(也称为DateTime?),还是仅仅使用DateTime?后者是一个值类型,其默认值恰好是01/01/0001 00:00:00


根据将 null 分配给 可能是 日期的代码示例,我们知道它不能是 DateTime;因此 DateTime? 是最有可能的。 - Marc Gravell
@NikolaDimitroff 这是在我将模型与数据库链接时,EntityFramework生成的一个 System.DateTime?。这就是为什么我可以给它一个 'null' 值,但我不知道为什么它会将其更改为默认值。 - Alex

0
关于ADO.NET(至少在.NET 4.7版本中),传递null(例如使用ExecuteNonQuery)将被翻译为SQL DEFAULT关键字。
可以使用SQL Server Profiler进行验证。
例如,以下代码:
var sqlCommand = new SqlCommand();
sqlCommand.CommandText = "EXEC CreateLog @UserName, @CreatedOn";
sqlCommand.Parameters.AddWithValue("@UserName", "George");
sqlCommand.Parameters.AddWithValue("@CreatedOn", (DateTime?)null);
sqlCommand.ExecuteNonQuery();

被翻译成:

exec sp_executesql N'EXEC CreateLog @UserName, @CreatedOn',
    N'@UserName nvarchar(6), @CreatedOn nvarchar(4000)',
    @UserName=N'George',@CreatedOn=default

通常情况下,这应该只会导致以下错误:

参数化查询[...]需要提供参数“@CreatedOn”,但未提供。

更多详细信息请参见此答案


0

当你编写迁移时,请注意输入 defaultValue:null 并且在模型类中将 DateTime? 也设置好。

public DateTime? FieldEx { get; set; }

migrationBuilder.AddColumn<DateTime>(
               name: "FieldEx",
               table: "tableEx",
               type: "datetime2",
               nullable: true,
               defaultValue:null); 

-3

在Python编程语言中,该代码的返回类型为:

print(type(df['col_name'].get(key='0001-01-01 BC')))
<class 'NoneType'>

它不是空的,更具体地说,它是 NoneType 类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接