System.Data.SqlClient.SqlException: ''9' 附近的语法不正确

System.Data.SqlClient.SqlException: 'Incorrect syntax near '9'

我在 winform 中有两个 DateTimePickers(dateStart 和 dateStop)。我设置了 dateStart 和 dateSop 的格式如下:

    dateStart.Format = DateTimePickerFormat.Custom;
    dateStart.CustomFormat = "yyyy:MM:dd HH:mm:ss";
    dateStop.Format = DateTimePickerFormat.Custom;
    dateStop.CustomFormat = "yyyy:MM:dd HH:mm:ss";

我想计算我的数据库 table 在 dateStart 和 dateStop 之间的行数。 我的 select 字符串:

string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN  " + Convert.ToString(dateStart.Value) + " AND " + Convert.ToString(dateStop.Value);

结果是:

这就是 link 使用 DateTimePickers 为我的数据库设置 DateStart 和 DateStop 参数的方式。

 cmd.Parameters.Add("@DataStart", SqlDbType.DateTime).Value = dateStart.Value;// new DateTime(dateStart.Value);
 cmd.Parameters.Add("@DataStop", SqlDbType.DateTime).Value = dateStop.Value;// new DateTime(2020, 02, 05, 13, 12, 25, 703);//2020, 02, 05, 13, 12, 25, 703   //2020, 02, 05, 13, 06, 50, 700

行计数在没有 WHERE 子句的情况下工作得很好。

count = (int)cmdCount.ExecuteScalar();//this is how I count the rows

我要到这里 'System.Data.SqlClient.SqlException: Incorect syntax near 9'。

我有点不明白为什么如果dateStart的格式是"yyyy:MM:dd HH:mm:ss",dateStart.value会以另一种格式返回。在我的 UI 上,dateStart 以正确的格式显示(上面代码中的格式)。但我可能在我的 stmt 字符串中做了一些错误的事情。 有什么想法不对吗?

编辑 1(我的整个代码):

 private void button_Click(object sender, EventArgs e)
    {
        dateStart.Format = DateTimePickerFormat.Custom;
        dateStart.CustomFormat = "yyyy:MM:dd HH:mm:ss";
        dateStop.Format = DateTimePickerFormat.Custom;
        dateStop.CustomFormat = "yyyy:MM:dd HH:mm:ss";
        string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN  @DataStart AND @DataStop";         // WHERE DateTime BETWEEN  " + Convert.ToString(dateStart.Value) + " AND " + Convert.ToString(dateStop.Value)
       // string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN  '" + Convert.ToString(dateStart.Value) + "' AND '" + Convert.ToString(dateStop.Value) + "'";
        int count = 0;

        using (SqlConnection connection = new SqlConnection(@"Data Source=DESKTOP-JQSJAF8\SQLEXPRESS;Initial Catalog=TRTF_TagLogging;Integrated Security=True; MultipleActiveResultSets = true")) 
        {
            using (SqlCommand cmd = new SqlCommand("PS_TagLogging", connection))// used for stored proc
            {
                using (SqlCommand cmdCount = new SqlCommand(stmt, connection))//used to count number of rows of my table
                {
                    //yyyy:MM:dd hh:mm:ss
                    connection.Open();
                    cmd.CommandType = CommandType.StoredProcedure;                        
                    cmd.Parameters.Add("@DataStart", SqlDbType.DateTime).Value = dateStart.Value;
                    cmd.Parameters.Add("@DataStop", SqlDbType.DateTime).Value = dateStop.Value;
                    var values = new List<double>();
                    var valData = new List<DateTime>();
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        // values.Add(reader.GetInt64(0));//reads the values of first column (ID) from DB
                        values.Add(reader.GetFloat(1));//reads the values of second column (Tag1) from DB 
                        valData.Add(reader.GetDateTime(2));//reads the values of third column (DateTime) from DB 
                    }

                    arrDate = valData.ToArray();
                    arrVal = values.ToArray();

                    count = (int)cmdCount.ExecuteScalar();
                    plot1.XAxes[0].ScaleDisplay.TextFormatting.Style = Iocomp.Types.TextFormatDoubleStyle.DateTime;
                    plot1.XAxes[0].ScaleRange.Span = 1.0 / 120.0 ; //30sec Span;



                    for (int i=0; i<count; i++)
                    {
                        plot1.Channels.Trace[0].AddXY(arrDate[i], arrVal[i]);
                    }


                    connection.Close();
                }
            }
        }
        MessageBox.Show("Nr. lines: " + count);
         Random().NextDouble() * 100);
    }

正如评论中已经提到的和您的其他命令所证明的那样,您应该使用参数。在你的情况下它应该是这样的:

string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN @DataStart AND @DataEnd";
using (var cmd = new SqlCommand(stmt))
{
    cmd.Parameters.Add("@DataStart", SqlDbType.DateTime).Value = dateStart.Value;
    cmd.Parameters.Add("@DataStop", SqlDbType.DateTime).Value = dateStop.Value;
    var reader = cmd.ExecuteReader();

    // Process the data from the reader.
}

但也许您应该考虑完全放弃这些东西并使用 Entity Framework(核心)并为您的 DBContext 建模,然后只使用 LINQ-to-SQL 来检索数据来自您的数据库。

更新

在你更新了你的问题并发布了整个函数之后,这个问题就很简单了。您只是错过了将参数添加到第二个查询中,而仅将其添加到第一个查询中。所以请相应地更新为这样的内容:

cmdCount.Parameters.Add("@DataStart", SqlDbType.DateTime).Value = dateStart.Value;
cmdCount.Parameters.Add("@DataStop", SqlDbType.DateTime).Value = dateStop.Value;
count = (int)cmdCount.ExecuteScalar();

尽管如此,我希望这不是您的全部功能,因为在那种情况下,通过第二个查询请求计数是完全无用的。您使用该值迭代从第一个查询中提取的数组。所以我的假设是变量 arrDate.LengtharrVal.Length 已经包含您需要的值。因此,您应该真正检查这些值(数组的长度 属性 和查询的计数结果)是否相同,如果不相同,请检查它们不同的原因并找出导致此问题的根本原因。如果它们相同,只需使用您本地现有的值,而不必费心向 SQL serverb 询问您已经知道的内容。

人们所说的一切都很好,但我认为有遗漏的引号。尝试:

string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN  '" + Convert.ToString(dateStart.Value) + "' AND '" + Convert.ToString(dateStop.Value) + "'";