2012-07-17 222 views
1

我正在从一个访问数据库中拉出一个字符串字段的程序,从日期中分离出一个名称(第一个和最后一个),然后将该名称与日期分开存储在不同的访问中数据库。参数化的查询和NULL DateTime值

我已经完成了一切,除了一些日期值为空,所以我需要参数化SQL,但我一直无法弄清楚如何使参数化工作。

我已经为变量放入了虚拟值,并将它们添加到表格中。我已经删除了下面的代码片段中的其他变量,因为它们都是重复的。 os是一个包含结构数据的列表。

string sqlcmd = "INSERT INTO signatures VALUES ('" + os.QASignature + "', 'QADate = @QADATE'"; 
System.Data.OleDb.OleDbCommand SQLCommand = new System.Data.OleDb.OleDbCommand(sqlcmd, Connection); 
using (SQLCommand) 
{ 
    SQLCommand.Parameters.Add("@QADATE", System.Data.OleDb.OleDbType.Date).Value = os.QADate; 
    SQLDataReader = SQLCommand.ExecuteReader(); 
} 

回答

4

像下面这样的东西应该是你想要的:

string sqlcmd = "INSERT INTO signatures (QASignature, QADate) VALUES (?, ?)"; 
using (System.Data.OleDb.OleDbCommand SQLCommand = new System.Data.OleDb.OleDbCommand(sqlcmd, Connection)) 
{ 
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "QASignature", Value = os.QASignature, DbType = DbType.String}); 
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "QADATE", Value = os.QADate, DbType = DbType.DateTime}); 
    SQLCommand.ExecuteNonQuery(); //Use ExecuteReader or ExecuteScalar when you want to return something 
} 

如果os.QADate为空(DateTime?System.Nullable<DateTime>),那么你会做到以下几点:

if(os.QADate == null) //Could easily be os.QADate == DateTime.MinValue too, for example 
{ 
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "@QADATE", Value = DBNull.Value, DbType = DbType.DateTime}); 
} 
else{ 
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "@QADATE", Value = os.QADate, DbType = DbType.DateTime}); 
} 

请注意,您不应该像你原来的例子那样混合字符串连接和参数 - 它是一个或另一个!实际上,它应该是只是参数化,以防止SQL注入,并获得其他好处(如更容易打字,并在某些RDBMS中,参数化查询执行得更好)。

另请注意,OleDBCommand不会从命名参数中受益 - 参数必须按它们在SQL中出现的顺序添加到查询中。这就是为什么SQL查询包含两个问号 - 它们只是占位符。

+0

后,我将它放入我的计划,我得到了以下错误执行: “‘价值’这个名字确实NT在目前情况下存在” “'System.Data.DbType'是一个'类型',但像'变量'一样使用。 – Donnachaidh 2012-07-18 16:04:07

+0

Nevermind,它需要像“SQLCommand.Parameters.Add(新的OleDbParameter(Name =”QASignature“,DbType.String).Value = os.QASignature)”而不是你所拥有的。 – Donnachaidh 2012-07-18 16:11:48

+0

感谢您的帮助。 – Donnachaidh 2012-07-18 16:12:01

4

你需要 “转换” nullDBNull.Value。实现这一点的一种方式,假设QADate是可以为空的DateTime(所以DateTime?)可能是:

... .Value = os.QADate ?? DBNull.Value; 

??是null-coalescing operator

编辑:您可能确实需要投以确保两个操作数是同类型的:

... .Value = (object)os.QADate ?? DBNull.Value; 

而且,你为什么不使用QASignature参数?你为什么“内联”这个价值?我不知道QASignature包含什么,但这会让您容易受到SQL Injection的影响。

最后,为什么你使用ExecuteReader()来插入?为什么不使用ExecuteNonQuery()

0

使用DBNull.Value

SQLCommand.Parameters.Add("@QADATE", 
          System.Data.OleDb.OleDbType.Date).Value = DBNull.Value; 

作为一个侧面说明,使用OleDbParameterCollection.AddWithValue自动推断的数据类型,并允许您缩短您的代码:

SQLCommand.Parameters.AddWithValue("@QADATE", DBNull.Value); 
0

考虑使用Nullable(of T)结构。然后,只有在源对象中实际存在变量时才可以进行设置。否则,该值将设置为Null,并很好地将其自身传递到SQL参数中。很多旧的TableAdapter类和更新的EntityFramework对象也都可以使用Nullable(T)结构。

1

DateTime不能为空,如果该值未初始化,则为DateTime.MinValue。 您需要测试这种情况,并将这些参数也用于字符串值。

using System.Data.OleDb; 
.... 

string sqlcmd = "INSERT INTO signatures VALUES (@QASignature, @QADATE)"; 
using(OleDbCommand SQLCommand = new OleDbCommand(sqlcmd, Connection)) 
{ 
    SQLCommand.Parameters.AddWithValue("@QASignature", os.QASignature); 
    SQLCommand.Parameters.Add("@QADATE", OleDbType.Date).Value = 
       (os.QADate == DateTime.MinValue 
       ? (object)DBNull.Value 
       : (object)os.QADate); 
    SQLDataReader = SQLCommand.ExecuteNonQuery(); 
} 

顺便说一句,一个INSERT语句通常是由ExecuteNonQuery

+0

'DateTime'确实不能为null,'DateTime?'但是,可以:-)我假设后者自user1533116指出'某些日期值为空'。 – RobIII 2012-07-17 22:38:00

+0

对不起,@Steve,我不小心编辑了你的帖子。已回滚到原始版本。我删除了System.Data.OleDb.OleDbCommand部分,所以没有改变它的性质。我必须失明。 – dash 2012-07-17 22:47:04

+0

@dash,好的,但是你的编辑是正确的。让我恢复您的更改:-) – Steve 2012-07-17 22:49:21