【问题标题】:MySql and inserting last ID problem remainsMySql 和插入最后一个 ID 问题仍然存在
【发布时间】:2025-12-03 18:00:01
【问题描述】:

好的,经过大量阅读和尝试,我似乎仍然无法让它工作:

      OdbcCommand cmd = new OdbcCommand("INSERT INTO User (Email) VALUES ('rusty@msn.com'); SELECT LAST_INSERT_ID();", cn);

cmd.ExecuteNonQuery();
                using (OdbcDataReader reader = cmd.ExecuteReader())
                {

                string theUserId = String.Format("{0}", reader.GetString(0));
                Label10.Text = theUserId;

表格:

User
--------
UserID (auto increment, pk)
Email

在调试模式下运行我在这一行得到错误,

            using (OdbcDataReader reader = cmd.ExecuteReader())

和,

cmd.ExecuteNonQuery();

Mysql 在这一行说它是一个语法错误SELECT LAST_INSERT_ID();", cn);但据我所知,这是合法的。

确切的错误:

ERROR [42000] [MySQL][ODBC 3.51 Driver][mysqld-5.5.9]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT LAST_INSERT_ID()' at line 1

编辑:贾斯汀方法:

using (OdbcConnection connection = new OdbcConnection("Driver={MySQL ODBC 3.51 Driver}; Server=localhost; Database=gymwebsite2; User=root; Password=commando;"))
{
    // ODBC command and transaction objects
    OdbcCommand command = new OdbcCommand();
    OdbcTransaction transaction = null;

    // tell the command to use our connection
    command.Connection = connection;

    try
    {
        // open the connection
        connection.Open();

        // start the transaction
        transaction = connection.BeginTransaction();

        // Assign transaction object for a pending local transaction.
        command.Connection = connection;
        command.Transaction = transaction;

        // TODO: Build a SQL INSERT statement
        OdbcCommand cmd = new OdbcCommand("INSERT INTO User (Email, FirstName, SecondName, DOB, Location, Aboutme, username, password) VALUES ('" + TextBox1.Text + "', '" + TextBox2.Text + "', '" + TextBox3.Text + "', '" + TextBox4.Text + "', '" + TextBox5.Text + "', '" + TextBox6.Text + "', '" + TextBox7.Text + "', '" + TextBox8.Text + "')", connection); 

        // run the insert using a non query call
        command.CommandText = cmd.ToString();
        command.ExecuteNonQuery();

        /* now we want to make a second call to MYSQL to get the new index 
           value it created for the primary key.  This is called using scalar so it will
            return the value of the SQL  statement.  We convert that to an int for later use.*/
        command.CommandText = "select last_insert_id();";
        id = Convert.ToInt32(command.ExecuteScalar());

        // the name id doesnt not exist in the current context

        // Commit the transaction.
        transaction.Commit();
    }
    catch (Exception ex)
    {
        Label10.Text = ": " + ex.Message;

        try
        {
            // Attempt to roll back the transaction.
            transaction.Rollback();
        }
        catch
        {
            // Do nothing here; transaction is not active.
        }
    }
}

【问题讨论】:

  • 是否允许在 1 个OdbcCommand 中执行 2 个查询/语句?如果你在 2 个不同的地方做会发生什么?
  • @Wrikken,这就是问题所在,.net mySQL ODBC 驱动程序不允许在该上下文中使用多个命令。您必须拨打两个单独的电话。我以前遇到过这个问题;)
  • 尝试使用字符串而不是使用字符串和连接参数创建另一个 OdbcCommand 对象。然后将 command.CommandText 设置为该字符串。我认为当您创建第二个 OdbcCommand 对象时会发生一些奇怪的事情。

标签: c# asp.net mysql


【解决方案1】:

解决方法:

  1. 在查询中添加输出参数:
  2. 在查询中使用 SET @OpParam = SELECT LAST_INSERT_ID();
  3. 在您的代码中获取它,就像 ((int)@OpParam.Value > 0){ pull out }。
  4. 另外,如果运行 select 然后代替 NonQuery,请使用 ExecuteScalar()。

希望对你有帮助。

【讨论】:

  • executescalar 用于选择。尝试设置一个参数仍然没有乐趣
  • 如果您需要检索第一个单元格的值,您还可以与插入、更新删除或多个语句一起使用
  • 如果您要返回身份并在代码中需要它,那么您需要 ExecuteScalar,而不是 NonQuery,因为 Non Query 将为您提供受查询影响的行数。
【解决方案2】:

澄清,mySQL .net ODBC 驱动程序不允许像您描述的那样运行多个命令。您必须进行两个单独的调用并将它们包装在一个事务中。

// open a new connection using a default connection string I have defined elsewhere
using( OdbcConnection connection = new OdbcConnection( s_connectionString ) )
{
      // ODBC command and transaction objects
      OdbcCommand command = new OdbcCommand();
      OdbcTransaction transaction = null;

      // tell the command to use our connection
      command.Connection = connection;

      try
      {
           // open the connection
           connection.Open();

           // start the transaction
           transaction = connection.BeginTransaction();

           // Assign transaction object for a pending local transaction.
           command.Connection = connection;
           command.Transaction = transaction;

           // TODO: Build a SQL INSERT statement
           StringBuilder SQL = new StringBuilder();

           // run the insert using a non query call
           command.CommandText = SQL.ToString();
           command.ExecuteNonQuery();

           /* now we want to make a second call to MYSQL to get the new index 
              value it created for the primary key.  This is called using scalar so it will
               return the value of the SQL  statement.  We convert that to an int for later use.*/
           command.CommandText = "select last_insert_id();";
           id = Convert.ToInt32( command.ExecuteScalar() );

           // Commit the transaction.
           transaction.Commit();
     }
     catch( Exception ex )
     {
          Debug.WriteLine( ex.Message );

          try
          {
               // Attempt to roll back the transaction.
               transaction.Rollback();
            }
            catch
            {
                 // Do nothing here; transaction is not active.
              }
         }
}

【讨论】:

  • 我收到一个错误:错误 [42000] [MySQL][ODBC 3.51 驱动程序][mysqld-5.5.9]您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“System.Data.Odbc.OdbcCommand”附近使用正确的语法
【解决方案3】:

如果您的电子邮件是唯一的,您可以使用

Select ID From User where Email='rusty@msn.com'

你确信你总是能得到正确的答案。

如果您的电子邮件不是唯一的,您应该使用锁定来确保只有在线程上执行查询,然后在插入后使用此查询

Select Max(ID) From User

【讨论】:

  • 啊抱歉,这封电子邮件只是一个例子,我不知道这封电子邮件,直到它插入数据库,因此我需要最后一笔交易