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.Length
和 arrVal.Length
已经包含您需要的值。因此,您应该真正检查这些值(数组的长度 属性 和查询的计数结果)是否相同,如果不相同,请检查它们不同的原因并找出导致此问题的根本原因。如果它们相同,只需使用您本地现有的值,而不必费心向 SQL serverb 询问您已经知道的内容。
人们所说的一切都很好,但我认为有遗漏的引号。尝试:
string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN '" + Convert.ToString(dateStart.Value) + "' AND '" + Convert.ToString(dateStop.Value) + "'";
我在 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.Length
和 arrVal.Length
已经包含您需要的值。因此,您应该真正检查这些值(数组的长度 属性 和查询的计数结果)是否相同,如果不相同,请检查它们不同的原因并找出导致此问题的根本原因。如果它们相同,只需使用您本地现有的值,而不必费心向 SQL serverb 询问您已经知道的内容。
人们所说的一切都很好,但我认为有遗漏的引号。尝试:
string stmt = "SELECT COUNT(*) FROM [dbo].[tbl_TagLogging] WHERE DateTime BETWEEN '" + Convert.ToString(dateStart.Value) + "' AND '" + Convert.ToString(dateStop.Value) + "'";