【问题标题】:MySQL Error In C# - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntaxC# 中的 MySQL 错误 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法
【发布时间】:2021-07-18 20:26:29
【问题描述】:

您的 SQL 语法有误;检查与您的 MySQL 服务器版本相对应的手册,以了解在附近使用的正确语法

我尝试在 C# 中同时使用两个 SQLDataReader。但是有一个错误。行中的错误:

 MySqlDataReader dr3 = cmdd3.ExecuteReader();
 MySqlDataReader dr4 = cmdd4.ExecuteReader();

代码:

MySqlConnection con1 = new MySqlConnection("Data Source =123.456.78.910; user id = root; password=12345;persistsecurityinfo=True; database=trydata");

con1.Open();

MySqlCommand cmdd3 = new MySqlCommand("Select Count(Distinct(SN) from uat.station where StationNumber = @Station and Status = @status and Date_Time between @DateFrom and @DateTo)", con1);

MySqlCommand cmdd4 = new MySqlCommand("Select Count(Distinct(SN) from uat.station where StationNumber = @Station and Status = @status and Date_Time between @DateFrom and @DateTo)", con1);

for (int i = 0; i < 11; i++) //for loop to run query simultaneously 11times and store data in array
{
     if (i == 0)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 1");
      cmdd4.Parameters.AddWithValue("@Station", "Station 1");
     }
     else if (i == 1)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 2");
      cmdd4.Parameters.AddWithValue("@Station", "Station 2");
     }
     else if (i == 2)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 3");
      cmdd4.Parameters.AddWithValue("@Station", "Station 3");
     }
     else if (i == 3)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 4");
      cmdd4.Parameters.AddWithValue("@Station", "Station 4");
     }
     else if (i == 4)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 5");
      cmdd4.Parameters.AddWithValue("@Station", "Station 5");
     }
     else if (i == 5)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 6");
      cmdd4.Parameters.AddWithValue("@Station", "Station 6");
     }
     else if (i == 6)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 7");
      cmdd4.Parameters.AddWithValue("@Station", "Station 7");
     }
     else if (i == 7)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 8");
      cmdd4.Parameters.AddWithValue("@Station", "Station 8");
     }
     else if (i == 8)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 9");
      cmdd4.Parameters.AddWithValue("@Station", "Station 9");
     }
     else if (i == 9)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 10");
      cmdd4.Parameters.AddWithValue("@Station", "Station 10");
     }
     else if (i == 10)
     {
      cmdd3.Parameters.AddWithValue("@Station", "Station 11");
      cmdd4.Parameters.AddWithValue("@Station", "Station 11");
     }

    cmdd3.Parameters.AddWithValue("@status", "PASS");
    cmdd3.Parameters.AddWithValue("@workorder", TextBox3.Text);
    cmdd3.Parameters.AddWithValue("@DateFrom", dateTimeFrom);
    cmdd3.Parameters.AddWithValue("@DateTo", dateTimeTo);
                    
    cmdd4.Parameters.AddWithValue("@status", "FAIL");
    cmdd4.Parameters.AddWithValue("@workorder", TextBox3.Text);
    cmdd4.Parameters.AddWithValue("@DateFrom", dateTimeFrom);
    cmdd4.Parameters.AddWithValue("@DateTo", dateTimeTo);

    MySqlDataReader dr3 = cmdd3.ExecuteReader();
    MySqlDataReader dr4 = cmdd4.ExecuteReader();
    if (dr3.HasRows && dr4.HasRows)
      {
       while (dr3.Read() && dr4.Read())
       {
         string firstColum = (i + 1).ToString();
         string secondColum = stationName[i]; //pass stations name
         string thirdColum = dr3.GetValue(0).ToString(); //pass data SN PASS to thirdColum
         string fourthColum = dr4.GetValue(0).ToString(); //pass data SN FAIL to fourthColum
         string fifthColum = (Convert.ToInt32(thirdColum) + Convert.ToInt32(fourthColum)).ToString(); //count the total of PASS & FAIL
         string sixthColum = ((Convert.ToInt32(thirdColum) / Convert.ToInt32(fifthColum)) * 100).ToString("F"); //Calculate yield of PASS (pass/total)*100 ..

         DataTable dtable = new DataTable();
         dtable.Columns.Add(new DataColumn("No."));
         dtable.Columns.Add(new DataColumn("Station Name"));
         dtable.Columns.Add(new DataColumn("Pass SN"));
         dtable.Columns.Add(new DataColumn("Fail SN"));
         dtable.Columns.Add(new DataColumn("Total"));
         dtable.Columns.Add(new DataColumn("Yield Pass"));

         RowValues[0] = firstColum;
         RowValues[1] = secondColum;
         RowValues[2] = thirdColum;
         RowValues[3] = fourthColum;
         RowValues[4] = fifthColum;
         RowValues[5] = sixthColum;

         DataRow dRow;
         dRow = dtable.Rows.Add(RowValues);
         dtable.AcceptChanges();
 
         dataGridView1.DataSource = dtable;
         dataGridView1.DataBind();

         con1.Close();
         }
}

这是否意味着我不能将两个 SQLDataReader 与 1 个连接字符串一起使用? 我也尝试在 web.config 中设置 MultipleActiveResultSets=true 但错误仍然相同。

错误图片:

【问题讨论】:

  • 嗨@Seracens,您能否在您的问题中为cmdd3 提供完整的SQLCommand?正如它所提到的,您的查询命令中存在语法错误。谢谢。
  • 也分享您正在触发的查询,它必须与此相关
  • 您好@YongShun,我已经更新了代码。您可能会在第 3 行看到 cmdd3 的 SQL 命令
  • 嗨@RanjitSingh,您所说的查询触发是什么意思?是命令查询吗?

标签: c# mysql asp.net


【解决方案1】:

1.0 问题(S)

您的查询错误地关闭了 COUNT() 的括号

Select Count(Distinct(SN) from uat.station where StationNumber = @Station and Status = @status and Date_Time between @DateFrom and @DateTo)

1.1 解决方案:修复COUNT()的不正确语法

Select Count(Distinct(SN)) from uat.station where StationNumber = @Station and Status = @status and Date_Time between @DateFrom and @DateTo

2.0 关注(S)

2.1 关注点:在 COUNT() 中应用 DISTINCT 可能会导致计算错误

假设SNuat.station表中的列,计算查询记录中出现的记录数,不需要在查询中使用DISTINCT

DISTINCT

从结果集中删除列中的重复值

SN列不唯一时,在COUNT中应用DISTINCT(SN)可能会导致计算错误。

COUNT(DISTINCT(SN))

如果 SN 列 NOT UNIQUE:对于 非重复 SN 值 记录返回 COUNT = M

如果 SN 列是 UNIQUE:对于 ALL 记录返回 COUNT = N

COUNT(SN)

ALL 条记录返回 COUNT = N

2.1 解决方案:从查询中删除DISTINCT()

SELECT StationNumber,
    Count(SN) 
FROM uat.station 
WHERE StationNumber = @Station 
  AND Status = @status 
  AND Date_Time between @DateFrom and @DateTo

2.2 关注点:是否需要通过循环将值传递给@Station?而WHERE StationNumber = @Station 不正确

循环将值添加到@Station 可能会导致您的结果输出不正确。此外,在比较多个值时,您在 WHERE 部分中的 @Station 应使用 IN

2.2.1(第一个可选)解决方案:如果尝试查询所有站并应用GROUP BY

,请删除@Station 参数
SELECT StationNumber,
    Count(StationNumber) 
FROM uat.station 
WHERE Status = @status 
  AND Date_Time between @DateFrom and @DateTo
GROUP BY StationNumber

2.2.2(第二个可选)解决方案:使用IN 比较@Station 参数的每个值(需要)并应用GROUP BY。 [不推荐,但取决于需要]

SELECT StationNumber,
    Count(StationNumber) 
FROM uat.station 
WHERE StationNumber IN @StationNumber
  AND Status = @status 
  AND Date_Time between @DateFrom and @DateTo
GROUP BY StationNumber

3.0 建议

3.1 将cmdd3 & cmdd4 合并为1个查询进行计算

cmd3cmd4 查询可以合并为 1 个查询,因为 MySqlCommandMySqlDataReader 与不同的 @Status 共享同一个查询。

注意:我使用 2.2.1 解决方案来扩展 3.1 推荐

SELECT
    StationNumber
    , PassCount
    , FailCount
    , TotalCount
    , CAST((PassCount * 100 / TotalCount) AS DECIMAL(5,2)) AS PassPercentage
FROM 
(
    SELECT 
        StationNumber,
        SUM(CASE WHEN [Status] = 'PASS' THEN 1 ELSE 0 END) AS PassCount,
        SUM(CASE WHEN [Status] = 'FAIL' THEN 1 ELSE 0 END) AS FailCount,
        COUNT([Status]) AS TotalCount
    FROM uat.station
    WHERE Date_Time between @DateFrom and @DateTo
    GROUP BY StationNumber
) a

3.2 停止使用AddWithValue()

使用AddWithValue() 可能会导致您的命令参数和表列的数据类型不匹配。相反,您需要将命令参数中的确切数据类型作为相应的数据库表列传递。

cmdd3.Parameters.Add("@Station", SqlDbType.NVarchar, 50).Value = "Station 1";
cmdd3.Parameters.Add("@Status", SqlDbType.Varchar, 10).Value = "PASS";  

参考:Can we stop using AddWithValue() already?


3.3 使用块/声明为MySqlConnectionMySqlCommandMySqlDataReader 应用

这些(通过 IDisposable 接口实现)将在进程结束或触发异常时自动释放资源。

Using statement

using (MySqlConnection con1 = new MySqlConnection(/* Connection string */))
{
    con1.Open();
    using (MySqlCommand cmd = new MySqlCommand(/* query */, con1))
    {
        // Add Parameter

        using (MySqlDataReader dr = cmd.ExecuteReader())
        {
             // Retrieve value from Data Reader
        }
    }
}

Using declaration for C#8.0

using MySqlConnection con1 = new MySqlConnection(/* Connection string */);
con1.Open();

using MySqlCommand cmd = new MySqlCommand(/* query */, con1);
// Add Parameter

using MySqlDataReader dr = cmd.ExecuteReader();
// Retrieve value from Data Reader

【讨论】:

  • 是的@YongShun,是的,我的命令查询错过了右括号。谢谢你发现这个错误。在我改变之后,错误就消失了。但是现在我卡在了 GridView1.DataBind();错误显示:DataBinding:“System.Data.DataRowView”不包含名为“ID”的属性。然后,我想使用您的替代解决方案,如果我可以将它作为 SelectCommand 放在 sqldatasource 中,然后绑定 gridview。这可能吗?
  • 其实我有6列No., Station Name, Pass SN, Fail SN, Total SN, and Yield。如何确保 Station Name 显示正确的数据,PassCount 为 Pass SN,FailCount 为 Fail SN,TotalCount 为 Total SN,As PassPercentage 为 Yield。在您的替代解决方案中,我是否必须在 PassCount 之前添加“Distinct(Station)”?不好意思问太多=(我是新手
  • 嗨@Seracens,我怀疑在您的.aspx (UI) 页面中,GridView 包含在列中的ID。 GridView 正在尝试检索您的 DataTable 不包含此 ID 列的 ID 列。您需要修改您的 GridView for ID 列是必需的。如果需要,请确保 DataTable 需要有 ID 列。
  • 您可以尝试插入我的替代解决方案,但需要确保您的 GridView 和 DataTable 具有准确的列。对于“在您的替代解决方案中的 PassCount 之前添加“Distinct(Station)”,需要知道您尝试实现的输出是什么。对于从我的查询返回的结果,它将仅返回 1 条记录,因为仅选择 1 个站。因此,不需要DISTINCT(Station)。但是您可以在选择部分添加StationNumber 或您需要的任何列。我添加到解决方案中。也许你可以参考一下。谢谢。
  • 我想提出的另一个问题是,是否有必要为@Station 循环添加“Station 1”等到 SqlParameter?这样你可能会得到错误的结果。如果要计算每个站,可以删除@Station 参数并使用GroupBy
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-01
  • 2022-01-14
  • 2019-03-25
  • 2015-10-23
相关资源
最近更新 更多