如何使用 MS Access 在 C# 中的两个日期之间进行搜索

Posted

技术标签:

【中文标题】如何使用 MS Access 在 C# 中的两个日期之间进行搜索【英文标题】:How to search between two dates in C# with MS Access 【发布时间】:2016-02-08 14:46:49 【问题描述】:

所以对于一个小组项目,我需要能够在两个日期“Start_Date”和“End_Date”之间进行搜索。这两个字段都使用数据库中的一个名为“study_date”的列。目前我只能通过在任一字段中输入指定日期来搜索一个日期。

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.OleDb;

namespace RRAS


    public partial class formRRAS : Form
    
        public OleDbConnection DataConnection = new OleDbConnection();


        public formRRAS()
        
            InitializeComponent();

        

        //When the form loads it sets the intial combo box RFR item to null
        private void formRRAS_Load(object sender, EventArgs e)
        
            // TODO: This line of code loads data into the 'database1DataSet.tblReject_test' table. You can move, or remove it, as needed.
            this.tblReject_testTableAdapter.Fill(this.database1DataSet.tblReject_test);

            cmbRFR.SelectedItem = "";

        

        //AddRFR method, called in the NewRFRPopup
        public void AddRFR(object item)
        
            cmbRFR.Items.Add(item);
        

        //The code for the button that closes the application
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        
            this.Close();
        

        private void btnSearch_Click(object sender, EventArgs e)
        

            //This creates the String Publisher which grabs the information from the combo box on the form.
            //Select and Dataconnection are also defined here.
                string Department = String.IsNullOrEmpty(txtDepartment.Text)? "%" : txtDepartment.Text;
                string Start_Date = String.IsNullOrEmpty(txtStart.Text)? "%" : txtStart.Text;
                //DateTime start = DateTime.Parse(Start_Date);
                string End_Date = String.IsNullOrEmpty(txtEnd.Text)? "%" : txtEnd.Text;
                string Anatomy = String.IsNullOrEmpty(txtAnatomy.Text)? "%" : txtAnatomy.Text;
                string RFR = String.IsNullOrEmpty(cmbRFR.Text) ? "%" : cmbRFR.Text;
                string Comment = String.IsNullOrEmpty(txtComment.Text)? "%" : txtComment.Text;

                string Select = "SELECT * FROM tblReject_test WHERE department_id LIKE '" + Department + "'" + "AND body_part_examined LIKE'" + Anatomy + "'" + "AND study_date LIKE'" + Start_Date + "'" + "AND study_date LIKE'" + End_Date + "'" + "AND reject_category LIKE'" + RFR + "'" +  "AND reject_comment LIKE'" + Comment + "'";

            //DataConnection connects to the database.
            string connectiontring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\Database1.mdb";
            DataConnection = new OleDbConnection(connectiontring);

            //The DataAdapter is the code that ensures both the data in the Select and DataConnection strings match.
            OleDbDataAdapter rdDataAdapter = new OleDbDataAdapter(Select, DataConnection);

            try
            
                //It then clears the datagridview and loads the data that has been selected from the DataAdapter.
                database1DataSet.tblReject_test.Clear();
                rdDataAdapter.Fill(this.database1DataSet.tblReject_test);
            
            catch (OleDbException exc)
            
                System.Windows.Forms.MessageBox.Show(exc.Message);
            
         //End of Search button

        //Temporary button thats loads the chart when clicked
        private void btnLoadChart_Click(object sender, EventArgs e)
        
            
                string connectiontring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\Database1.mdb";
                DataConnection = new OleDbConnection(connectiontring);

                try
                
                    int count = database1DataSet.Tables["tblReject_test"].Rows.Count;

                    DataConnection.Open();
                    OleDbCommand command = new OleDbCommand();
                    command.Connection = DataConnection;
                    string query = "SELECT * FROM tblReject_test";
                    command.CommandText = query;

                    OleDbDataReader reader = command.ExecuteReader();
                    while (reader.Read())
                    
                        charRejections.Series["RFR"].Points.AddXY(reader["reject_category"].ToString(), reader[count].ToString());
                    

                    DataConnection.Close();
                

                catch (Exception ex)
                
                    MessageBox.Show("Error " + ex);
                
            
         //end of load chart button


        //This button loads the NewRFRPopup form
        private void addRFRToolStripMenuItem_Click(object sender, EventArgs e)
        
            NewRFRPopup popup = new NewRFRPopup(this);
            popup.ShowDialog();
        
    

【问题讨论】:

不要使用字符串连接来生成 SQL 语句。使用适当的参数化查询。任何数量的有效字符都可能导致错误,例如注释I've tried but failed 将中断查询。 【参考方案1】:

你可以试试这个

string Select = "SELECT * FROM tblReject_test WHERE department_id LIKE '" + Department + "'" + "AND body_part_examined LIKE'" + Anatomy + "'" + "AND study_date >=#" + Start_Date + "#" + "AND study_date <=#" + End_Date + "#" + "AND reject_category LIKE'" + RFR + "'" +  "AND reject_comment LIKE'" + Comment + "'";

【讨论】:

我试过这个,每当我搜索时都会收到一条错误消息:“标准表达式中的数据类型不匹配”。 字符串连接是所有SQL注入罪恶的根源。使用参数化查询,以便'; DROP TABLE tblReject_test ;-- 的注释不会破坏您的数据库。或者输入 I've tried but I failed 之类的评论不会导致应用程序崩溃 如果您在数据库表中存储日期为 DATE 字段,则使用 # 而不是 '。查看编辑后的答案 使用 cdate(Start_Date) 和 cdate(End_Date) 因为它们是字符串而不是日期。此外,作为故障保险,您也可以将 study_date 转换为日期(如果它不是数据库中的日期)。 ....... "AND cdate(study_date) &lt;= cdate(" + Start_Date + ") AND cdate(study_date) &gt;= cdate(" + End_Date + ")..... 大家好,感谢您的回复。不幸的是,上述选项都没有奏效。 @DiscipleMichael,您能帮我将该代码放入完整的选择字符串中吗?当我尝试在当前状态下使用它时,它只是一团糟,根本不起作用。问候,亚伦【参考方案2】:

我认为其他几个人在这里提到了它,但永远不要在 SQL 中为您的“where”子句进行字符串连接。它只是在邀请各种各样的问题。

你想要的是参数,也就是绑定变量。这些用作占位符 - 一种说法,“编译此 SQL,稍后我会为您提供值。”

参数有很多优点:

    它们可以防止 SQL 注入 - 无论多么罕见和难以实现,这始终是可能的;为什么要冒险?尤其是当您的数据来自文本框时,您几乎是在求人尝试 它们使您的代码更加简洁。所有这些加号,单引号,双引号让我头晕目眩 您通常可以保持 SQL 的原始状态 - 将其复制并粘贴到您的 SQL 编辑器中,而无需修剪 SQL 连接中涉及的讨厌的字符。好的,所以这对于 Access 不是这样,但对于其他 RDBMS,能够剪切和粘贴会产生很大的不同 它们解析数据类型 - 您无需在 Access 日期周围放置 #hash 标记# 或对字符串执行任何特殊操作(甚至引号也不行) - 请参见下面的示例 它们处理特殊字符。例如,如果您的一个文本框包含I think I'll go to the park,则该撇号将转换为单引号,这会破坏您的查询。有了参数,你就不用担心了

以下是查询的参数化版本的示例:

string Select = @"
    SELECT * FROM tblReject_test
    WHERE
        department_id ALIKE @Department & '%'  AND
        body_part_examined ALIKE @Anatomy & '%' AND
        reject_category ALIKE @RFR & '%' AND
        reject_comment ALIKE @Comment & '%' and
        study_date >= @Start_Date and
        study_date <= @End_Date
";

OleDbCommand cmd = new OleDbCommand(Select, DataConnection);
cmd.Parameters.AddWithValue("@Department", txtDepartment.Text);
cmd.Parameters.AddWithValue("@Anatomy", txtAnatomy.Text);
cmd.Parameters.AddWithValue("@RFR", cmbRFR.Text);
cmd.Parameters.AddWithValue("@Comment", txtComment.Text);

DateTime startDate, endDate;
if (!DateTime.TryParse(txtStart.Text, out startDate))
    startDate = DateTime.MinValue;
if (!DateTime.TryParse(txtEnd.Text, out endDate))
    endDate = DateTime.MaxValue;

cmd.Parameters.AddWithValue("@Start_Date", startDate);
cmd.Parameters.AddWithValue("@End_Date", endDate);

另一个分离镜头 - 使用文本框作为日期 - 如果您使用日期/时间控件,这将更加清晰。解析会起作用,但对于控件本身的功能来说,需要付出很多额外的努力。

cmd.Parameters.AddWithValue("@Start_Date", dateTimePickerStart.Value);

哦,顺便说一句,我想我已经回答了您关于此建议解决方案中开始日期和结束日期之间的日期的问题。

【讨论】:

您好,感谢您提供有用的代码。虽然我不怀疑它是否有效,但我无法确认它,因为当我使用它并尝试在我的程序中搜索记录时,我收到一条弹出消息:“没有为一个或多个必需参数提供值” 这通常意味着这是一个错字——就像我创建了一个名为@Department 的参数,但实际上绑定了一个名为@Dept 的参数。我检查了代码,乍一看,一切都匹配。我可以模拟一个数据库并对其进行测试以查看是否得到相同的结果 嗯,我不确定...我模拟了它,它完全按预期工作。我能看到的唯一另一件事可能不同的是您使用的是 .mdb 文件,而我的是 .accdb。出于好奇,能不能换个新格式看看能不能用? 您好,很抱歉回复延迟。我曾尝试使用 .accdb 格式,但 Visual Studio 一直告诉我这是一种无法识别的数据库格式,这就是我选择使用 .mdb 的原因。

以上是关于如何使用 MS Access 在 C# 中的两个日期之间进行搜索的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用 OleDB 列出 MS Access 文件中的所有查询?

如何使用 C# 在 MS-Access 中的查询中使用带有通配符的 LIKE 运算符

如何通过 C# 以编程方式刷新 MS Access 链接表(使用 Excel 文件)?

使用 c# 和 oledb 查询更新 Ms-Access 2010 中的列值

如何在 C# 中更新或刷新与 Ms-access 连接的数据网格视图

如何使用 SQL 命令从我的 DataTable 对象中使用 foreach-loop 更新 C# 中的 MS Access 数据库?