【问题标题】:Can I execute multiple SQL statements?我可以执行多个 SQL 语句吗?
【发布时间】:2017-11-29 00:39:03
【问题描述】:

我正在为电影运行一个 sql 数据库,并且我正在开发这个功能,以便每当用户签出电影时,电影都会更新,说它已被签出,然后签出的电影将被添加到已签出电影的表格。我有一个运行没有任何错误的代码,但我签出的电影没有添加到我的签出表中。下面显示所选电影的网格视图代码:

<asp:ListBox ID="CheckOutList" runat="server" OnSelectedIndexChanged="Get_data" AutoPostBack="true">

        </asp:ListBox>

<asp:Panel ID="panel5" runat="server" Visible="false">
        <asp:GridView id="one_data" AutoGenerateColumns="false" runat="server" DataKeyNames="MovieID">
            <Columns>
                <asp:BoundField DataField="MovieID"
                    HeaderText="Movie ID"/>
                <asp:BoundField DataField="MovieTitle"
                    HeaderText="Movie"/>
                <asp:BoundField DataField="DateChecked"
                    HeaderText="Date Checked"/>
                <asp:BoundField DataField="CheckedOut"
                    HeaderText="Checked Out"/>
            </Columns>
        </asp:GridView>
        <asp:Button runat="server" Text="Choose another Movie" OnClick="GoBack" />
        <asp:Button runat="server" Text="Check Out" OnClick="CheckOut" />
    </asp:Panel>

查看电影的 CS 代码:

 public void CheckOut(object sender, EventArgs e)
    {
        get_connection();
        try
        {

            connection.Open();
            command = new SqlCommand("UPDATE Content SET DateChecked=@DateChecked, CheckedOut=@CheckedOut WHERE MovieID=@MovieID", connection);
            command.Parameters.AddWithValue("@DateChecked", DateTime.Now);
            command.Parameters.AddWithValue("@CheckedOut", 'Y');
            //command.Parameters.AddWithValue("@MovieID",);
            command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);

            reader = command.ExecuteReader();
            one_data.DataSource = reader;
            one_data.DataBind();

            reader.Close();


            command = new SqlCommand("INSERT INTO checkout (MovieID, SubscriberID) VALUES @MovieID, @SubscriberID", connection);
            command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);
            command.Parameters.AddWithValue("@SubscriberID", loginName.Text);
            command.ExecuteNonQuery();
        }
        catch (Exception err)
        {
            // Handle an error by displaying the information.
            lblInfo.Text = "Error reading the database. ";
            lblInfo.Text += err.Message;
        }
        finally
        {
            connection.Close();
            lblInfo.Text = "Movie Checked Out";

        }
    }

UPDATE SQL 语句确实有效,表示电影已被拍摄,但电影未添加到签出表中。

【问题讨论】:

  • 您应该阅读有关如何创建执行以下操作的存储过程SELECT, UPDATE, DELETE 如果还有关于规范化的任何关系表,我建议您在 SELECTS 需要的地方使用 JOINS 从而减少在如此多的数据库往返行程中。如果您使用的是 DataTables,我会尽可能地利用它来......不要使用相同的 db Connection 来执行 SELECTS、UPDATES 和 DELETES.. 创建 Connection 对象的新实例并利用 using(){ } 构造
  • 更新触发器怎么样,但是您的更新命令需要知道订阅者 ID 才能做到这一点,也就是登录名。
  • 关于使用不同方法的评论如潮水般涌来,毫无疑问,其中许多都是有价值的。但是要回答您提出的问题 - 是的,您可以执行多个语句。你的代码目前在做什么?您是否设置了断点并逐步完成了reader.close() 之后发生的事情?请注意,ExecuteNonQuery() 可以返回许多受影响的行,这可能对调试有用。
  • 我有一个用户在此之前访问的登录功能,并且正在使用来自订阅者ID的登录文本
  • @JackHuynh - 你试过调试它吗?即设置断点并单步执行。

标签: c# sql sql-server database


【解决方案1】:

我看到了一些缺失的概念。

  1. 为什么更新使用command.ExecuteReader(); 而插入使用command.ExecuteNonQuery();
    我认为你应该使用

执行非查询

  1. INSERT INTO checkout (MovieID, SubscriberID) VALUES @MovieID, @SubscriberID
    这个 sql 语法需要括号括起来:

插入结帐(MovieID、SubscriberID)值(@MovieID、@SubscriberID)

我希望这能解决你的问题。

【讨论】:

  • 赞成指出实际的语法错误。而且,@JackHuynh,finally 块在来自 INSERT 的语法错误时在 catch 块之后执行,从而成功覆盖错误文本消息。您应该将成功标记放在 try 块的末尾而不是 finally 块中。那么您可能会更早地注意到该错误。 (调试可能也发现了它。)
【解决方案2】:

我认为你最好在事务块中执行编码。您也可以使用“;”更新为以下示例

 connection.ConnectionString = connectionString;
 command.CommandText = @"
     UPDATE MultiStatementTest SET somevalue = somevalue + 1;
     UPDATE MultiStatementTest SET" + (generateError ? "WONTWORK" : "") + 
                   " somevalue = somevalue + 2;";
 command.CommandType = System.Data.CommandType.Text;
 command.Connection = connection;

【讨论】:

  • 我不建议建议 OP 创建动态 sql 存储过程会更可行,而且 OP 应该阅读 Sql Injection to
【解决方案3】:

我可以执行多条 SQL 语句吗?

当然可以!您可以在单个或多个SqlCommand 中执行它。 :)

UPDATE SQL 语句确实有效,表明电影已被拍摄,但 电影未添加到签出表中

您使用的是本地数据库吗?如果是,请查看Data not saving permanently to SQL table

无论如何,我希望我的数据访问代码可以帮助您的开发。

免责声明:我知道使用SqlCommand 作为参数更好,但我很懒所以这里是string 版本。

public interface IDAL
{
    void BeginTransaction();
    void EndTransaction();
    void SaveChanges();
    DataTable RetrieveData(string query, [CallerMemberName] string callerMemberName = "");
    string RetrieveString(string query, [CallerMemberName] string callerMemberName = "");
    bool ExecuteNonQuery(string query, [CallerMemberName] string callerMemberName = "");
    bool ExecuteNonQuery(string query, object[] parameters, [CallerMemberName] string callerMemberName = "");
}

public class MSSQLDAL : IDAL, IDisposable 
{
    private bool disposed = false;
    private string _connectionString { get; set; }
    private SqlTransaction _transaction { get; set; }
    private SqlConnection _connection { get; set; }
    private IsolationLevel _isolationLevel { get; set; }
    private bool _isCommitted { get; set; }

    public string ConnectionString
    {
        get { return _connectionString; }
    }

    public MSSQLDAL(string connectionString)
    {
        this.connectionString = _connectionString;
        this._connection = new SqlConnection();
        this._connection.ConnectionString = this._connectionString;
        this._isolationLevel = IsolationLevel.ReadCommitted;
        this._isCommitted = false;
    }

    public void BeginTransaction()
    {
        this.Open();
    }

    public void EndTransaction()
    {
        this.Close();
    }

    public void SaveChanges()
    {
        if(_transaction != null)
        {
            _transaction.Commit();
            this._isCommitted = true;
        }
        this.EndTransaction();
    }

    public DataTable RetrieveData(string query, [CallerMemberName] string callerMemberName = "")
    {
        DataTable dataTable = new DataTable();

        try
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.Transaction = _transaction;
                command.CommandText = query;
                command.CommandType = CommandType.Text;

                using (SqlDataAdapter dataAdapter = new SqlDataAdapter(command))
                {
                    dataAdapter.Fill(dataTable);
                }
            }

            //this.AuditSQL(query, string.Empty);
        }
        catch (Exception ex)
        {
            this.AuditSQL(query, ex.Message, callerMemberName);
        }

        return dataTable;
    }

    public string RetrieveString(string query, [CallerMemberName] string callerMemberName = "")
    {
        string text = string.Empty;

        try
        {
            using (SqlCommand oracleCommand = new SqlCommand())
            {
                oracleCommand.Connection = _connection;
                oracleCommand.Transaction = _transaction;
                oracleCommand.CommandText = query;
                oracleCommand.CommandType = CommandType.Text;

                using (SqlDataReader dataReader = oracleCommand.ExecuteReader())
                {
                    dataReader.Read();

                    text = dataReader.GetValue(0).ToString();
                }
            }

            //this.AuditSQL(query, string.Empty);

        }
        catch (Exception ex)
        {
            this.AuditSQL(query, ex.Message, callerMemberName);
        }

        return text;
    }

    public bool ExecuteNonQuery(string query, [CallerMemberName] string callerMemberName = "")
    {
        bool success = false;

        try
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.Transaction = _transaction;
                command.CommandText = query;
                command.CommandType = CommandType.Text;
                command.ExecuteNonQuery();
            }

            //this.AuditSQL(query, string.Empty);

            success = true;
        }
        catch (Exception ex)
        {
            this.AuditSQL(query, ex.Message, callerMemberName);

            success = false;
        }

        return success;
    }

    public bool ExecuteNonQuery(string query, object[] parameters, [CallerMemberName] string callerMemberName = "")
    {
        bool success = false;

        try
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.Transaction = _transaction;
                command.CommandText = query;
                command.CommandType = CommandType.Text;
                command.Parameters.AddRange(parameters);

                command.ExecuteNonQuery();
            }

            //this.AuditSQL(query, string.Empty);

            success = true;
        }
        catch (Exception ex)
        {
            this.AuditSQL(query, ex.Message, callerMemberName);

            success = false;
        }

        return success;
    }

    private void Open()
    {
        if(_connection.State == ConnectionState.Closed)
        {
            _connection.Open();
            _transaction = _connection.BeginTransaction(_isolationLevel);
        }            
    }

    private void Close()
    {
        if (!this._isCommitted)
        {
            if (this._transaction != null)
            {
                this._transaction.Rollback();
            }
        }
        if(this._connection.State == ConnectionState.Open)
        {
            this._connection.Close();
        }
    }

    private void AuditSQL(string query, string message, string callerMemberName = "")
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.AppendLine("**************************************************************************************************");
        stringBuilder.AppendLine(string.Format("DATETIME: {0}", DateTime.Now.ToString("MM/dd/yyyy HHmmss")));
        stringBuilder.AppendLine(string.Format("SQL: {0}", query));
        stringBuilder.AppendLine(string.Format("MESSAGE: {0}", message));
        if (!string.IsNullOrWhiteSpace(callerMemberName))
        {
            stringBuilder.AppendLine(string.Format("METHOD: {0}", callerMemberName));
        }
        stringBuilder.AppendLine("**************************************************************************************************");

        Logger.WriteLineSQL(stringBuilder.ToString()); // Log the query result. Add an #if DEBUG so that live version will no longer log.
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                if (!this._isCommitted)
                {
                    if (this._transaction != null)
                    {
                        this._transaction.Rollback();
                    }
                }
                this._transaction.Dispose();
                this._connection.Dispose();
            }
            // Free your own state (unmanaged objects).
            // Set large fields to null.
            // Free other state (managed objects).
            this._transaction = null;
            this._connection = null;
            disposed = true;
        }
    }
}

示例用法:

public void CheckOut(object sender, EventArgs e)
{
    string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString; // Assuming it is in your web.config

    try
    {
        using(MSSQLDAL dal = new MSSQLDAL(connectionString))
        {
            dal.BeginTransaction();

            string updateQuery = "UPDATE Content SET DateChecked=@DateChecked, CheckedOut=@CheckedOut WHERE MovieID=@MovieID";

            SqlParameter uDateChecked = new SqlParameter("DateChecked", SqlDbType.DateTime);
            uDateChecked = DateTime.Now;
            SqlParameter uCheckedOut = new SqlParameter("CheckedOut", SqlDbType.VarChar);
            uCheckedOut = 'Y';
            SqlParameter uMovieID = new SqlParameter("MovieID", SqlDbType.Int);
            uMovieID = CheckOutList.SelectedValue;

            ICollection<SqlParameter> updateParameters = new List<SqlParameter>();

            updateParameters.Add(uDateChecked);
            updateParameters.Add(uCheckedOut);
            updateParameters.Add(uMovieID);

            bool updateSuccessful = dal.ExecuteNonQuery(updateQuery, updateParameters.ToArray()); 

            string insertQuery = "INSERT INTO checkout (MovieID, SubscriberID) VALUES (@MovieID, @SubscriberID)";

            SqlParameter iSubscriberID = new SqlParameter("SubscriberID", SqlDbType.VarChar);
            iSubscriberID = loginName.Text;
            SqlParameter iMovieID = new SqlParameter("MovieID", SqlDbType.Int);
            iMovieID = CheckOutList.SelectedValue;

            ICollection<SqlParameter> insertParameters = new List<SqlParameter>();

            insertParameters.Add(iSubscriberID);
            insertParameters.Add(iMovieID);

            bool insertSuccessful = dal.ExecuteNonQuery(insertQuery, insertParameters.ToArray()); 

            if(updateSuccessful && insertSuccessful)
            {
                dal.SaveChanges();

                lblInfo.Text = "Movie Checked Out";
            }
            else
            {
                lblInfo.Text = "Something is wrong with your query!";
            }
        }   
    }
    catch(Exception ex)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("Error reading the database.");
        sb.AppendLine(ex.Message);
        if(ex.InnerException != null)
            sb.AppendLine(ex.InnerException.Message);

        lblInfo.Text = sb.ToString();
    }
}

如何在一个命令中执行多个 SQL 语句?

您只需使用BEGINEND; 封装您的查询。

例如:

BEGIN
    SELECT 'A';
    SELECT * FROM TableA;
END;

请注意,您需要在语句后加上;。如果我是你,我会使用StringBuilder 来写我的长查询。此外,仅当您不读取任何数据时,将多个查询作为一个发送才有用。

IDAL 接口有什么用?

在我的一些项目中,我不得不使用不同的数据库。使用相同的接口,我能够为 Oracle、MSSql 和 MySql 创建一个 DAL 类,而代码更改非常少。这也是OOP方式。 :)

【讨论】:

    【解决方案4】:

    请像这样更改代码,并在 executenonquery() 之后尝试更改 reader.close()。

    try
            {
    
                connection.Open();
                command = new SqlCommand("UPDATE Content SET DateChecked=@DateChecked, CheckedOut=@CheckedOut WHERE MovieID=@MovieID", connection);
                command.Parameters.AddWithValue("@DateChecked", DateTime.Now);
                command.Parameters.AddWithValue("@CheckedOut", 'Y');
                //command.Parameters.AddWithValue("@MovieID",);
                command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);
    
                reader = command.ExecuteReader();
                one_data.DataSource = reader;
                one_data.DataBind();
    
    
    
    
                command = new SqlCommand("INSERT INTO checkout (MovieID, SubscriberID) VALUES @MovieID, @SubscriberID", connection);
                command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);
                command.Parameters.AddWithValue("@SubscriberID", loginName.Text);
                command.ExecuteNonQuery();
    
               reader.Close();
            }
    

    【讨论】:

      【解决方案5】:

      我在阅读了所有帖子后终于找到了答案,发现这实际上让我的 INSERT 工作

      try
              {
      
                  connection.Open();
                  command = new SqlCommand("UPDATE Content SET DateChecked=@DateChecked, CheckedOut=@CheckedOut WHERE MovieID=@MovieID", connection);
                  command.Parameters.AddWithValue("@DateChecked", DateTime.Now);
                  command.Parameters.AddWithValue("@CheckedOut", 'Y');
                  //command.Parameters.AddWithValue("@MovieID",);
                  command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);
      
                  //reader = command.ExecuteReader();
                  command.ExecuteNonQuery();
                  one_data.DataSource = reader;
                  one_data.DataBind();
                  connection.Close();
      
      
      
                  connection.Open();
                  command = new SqlCommand("INSERT INTO checkout (MovieID, SubscriberID) VALUES (@MovieID, @SubscriberID)", connection);
                  command.Parameters.AddWithValue("@MovieID", CheckOutList.SelectedValue);
                  command.Parameters.AddWithValue("@SubscriberID", loginName.Text);
                  command.ExecuteNonQuery();
                  //reader.Close();
              }
      

      【讨论】:

      • 这不是一个好方法,因为你不断地关闭和打开连接。最好的方法是在一个打开的连接中完成。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      • 2017-04-28
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      相关资源
      最近更新 更多