[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]

 這種做法比較保險。推薦!

總結

這個知識點再容易不過了,估計很多初學者都會踩這樣的坑,不過還好,踩過了就長記性了,也是有好處的。為什么會有這樣的問題?可能你對伙伴比較信任,潛意識覺得他肯定會在數據庫中添加默認約束的。到最后中槍的還是自己。所以在設計程序,編寫代碼的時候,一定要嚴謹!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM