[SQL]躺着也中枪的datetime类型

写在前面

本来这个东西,我是不想在这里总结的,今天有初学者的朋友问我了,那就不得不说说了,你肯定也踩过这样的坑,没遇到,说明你运气好,编码习惯好。那还是言归正传吧。避免你中枪,还是扫一眼这篇文章吧。

一个例子

测试环境:sqlserver2012,vs2013

下面看一个简单的例子,例子非常简单,就不再写注释了。一个测试的数据表TB_UserInfo:

一个再简单不过的表,自增的id,用户名字,注册时间,从上图你也看到了,是允许为空的。

再弄一个简单的测试程序。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Data;
 7 using System.Data.SqlClient;
 8 namespace Wolfy.SQLDateTimeDemo
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             string strConn = "server=.;database=test;uid=sa;pwd=sa;";
15             string strSql = "insert into TB_userInfo values(@Name,@RegDateTime)";
16             UserInfo user = new UserInfo() { Name = "wolfy" };
17             try
18             {
19                 using (SqlConnection conn = new SqlConnection(strConn))
20                 {
21                     using (SqlCommand cmd = new SqlCommand(strSql, conn))
22                     {
23                         cmd.Parameters.Add(new SqlParameter("@Name", user.Name));
24                         cmd.Parameters.Add(new SqlParameter("@RegDateTime", user.RegDateTime));
25                         conn.Open();
26                         if (cmd.ExecuteNonQuery() > 0)
27                         {
28                             Console.WriteLine("注册成功");
29                         }
30                         else
31                         {
32                             Console.WriteLine("注册失败");
33                         }
34                     }
35                 }
36             }
37             catch (Exception ex)
38             {
39                 throw ex;
40             }
41         }
42     }
43     /// <summary>
44     /// 用户信息类
45     /// </summary>
46     class UserInfo
47     {
48         /// <summary>
49         /// 编号
50         /// </summary>
51         public int Id { set; get; }
52         /// <summary>
53         /// 姓名
54         /// </summary>
55         public string Name { set; get; }
56         /// <summary>
57         /// 注册时间
58         /// </summary>
59         public DateTime RegDateTime { set; get; }
60     }
61 }

我们知道,如果在使用类的属性的时候,你不为他赋值,则采用默认值。

可见它是有默认值的。

那我们继续往下走,再看看

出现了,这个异常,想必很多人都遇到过吧。

可以看出,vs中datetime类型的默认值与sqlserver中的datetime类型范围的确存在冲突。突然有这样的想法,为什么这两种默认值不兼容呢?考虑到现在的软件都会和数据库相结合,这样设计是不是有点不合理了?这东西,咱也是无法改变了,也只能选择接收了。尽量做到规范设计吧。

有两种做法可以解决这个问题:

方案一:

在添加数据的时候,为datetime类型的值赋值为当前时间。

1   UserInfo user = new UserInfo() { Name = "wolfy", RegDateTime=DateTime.Now };

方案二:

创建数据表的时候给时间类型的字段添加默认值约束

1 语法:
2 ALTER TABLE table_name
3 ADD CONSTRAINT constraint_name
4 DEFAULT constant_expression [FOR column_name]
5 参数说明:
6  table_name:要创建默认约束的表名称。
7  constraint_name:默认约束名称。
8  constant_expression:默认值。
1 alter table tb_userinfo add constraint default_RegDateTime default getdate() for [RegDateTime]

 这种做法比较保险。推荐!

总结

这个知识点再容易不过了,估计很多初学者都会踩这样的坑,不过还好,踩过了就长记性了,也是有好处的。为什么会有这样的问题?可能你对伙伴比较信任,潜意识觉得他肯定会在数据库中添加默认约束的。到最后中枪的还是自己。所以在设计程序,编写代码的时候,一定要严谨!

posted @ 2015-01-19 22:06  wolfy  阅读(2933)  评论(26编辑  收藏  举报