【问题标题】:How to Delete Data from Two tables in single query如何在单个查询中从两个表中删除数据
【发布时间】:2011-05-22 01:00:26
【问题描述】:

我有两个表:Accounts,其中包含用户拥有的帐户信息,AccountUsers,其中包含在上述Accounts 表中拥有帐户的用户列表。

如果我必须删除一个用户,那么我必须从两个表中删除它们,其中AccountUsers 将拥有该用户的一行,而其他用户可能有很多,因为单个用户可以拥有多个帐户。

我编写了以下代码,它运行良好并从两个表中删除了行,但是每当第二个表中有多行时,它就无法删除它们并且ExecuteNonQuery() 返回 0,这意味着 0 行受到影响。

我想知道它是否可以在一行中完成。另外,如何对第二个表中的多行执行此操作,因为我现有的代码仅在有单行时才有效。

代码:

public static bool DeleteUser(int UserId)
        {
            if (ConnectDatabase())
            {
                sql_cmd = new SqlCommand();
                sql_cmd.Connection = sql_con;
                sql_cmd.Parameters.Add("@userId", SqlDbType.Int).Value = UserId;
                sql_cmd.CommandText = "DELETE FROM AccountsUsers WHERE Id = @userId";

                if (sql_cmd.ExecuteNonQuery() == 1)
                {
                    sql_cmd = new SqlCommand();
                    sql_cmd.Connection = sql_con;
                    sql_cmd.Parameters.Add("@userId", SqlDbType.Int).Value = UserId;
                    sql_cmd.CommandText = "DELETE FROM Accounts WHERE userId = @userId";
                    if (sql_cmd.ExecuteNonQuery() == 1)
                    {
                        return true;
                    }
                    else
                        return false;

                }
                else
                    return false;
            }
            else
                return false;
        } 

【问题讨论】:

    标签: c# sql query-optimization


    【解决方案1】:

    您的代码中存在一些逻辑缺陷。如果第二个表中有一条记录,则 ExecuteNonQuery 将返回 1,但如果还有更多,它将返回一条,而是返回一些其他数字。我会将第二次删除后的条件更改为:

    if (sql_cmd.ExecuteNonQuery() > 1)
    

    这引发了一个问题 - 如果第二个表中没有记录,您是否希望您的函数返回 false?

    【讨论】:

    • 这是你所说的错误。实际上它在删除两行时返回 2 等等。我没想到,我以为只有 2 个值。0,1
    【解决方案2】:

    您可能需要先删除帐户,但不清楚您的外键的确切方向。

    您通常不能在一个查询中从两个表中删除,但您可以创建一个事务并在该事务中拥有两个 DELETE 语句。

    您还可以使用级联删除约束,以便仅从父表中删除(但我很少推荐这样做)。

    【讨论】:

    • 在 MySQL 中可以。 DELETE FROM AccountsUsers, Accounts USING AccountsUsers INNER JOIN Accounts WHERE AccountsUsers.Id = Accounts.userId AND AccountsUsers.Id = @userId
    • Accountstable 中有一个名为 Id 的主键,但我使用的是 userId 列,它是我在数据库表中插入值时填充的列。
    【解决方案3】:

    我可能太简单了,但您可能只需执行以下操作 - 在一个以分号分隔的命令中包含多个 sql 语句并没有错:

        static bool DeleteUser(int UserId)
        {
            if (ConnectDatabase())
            {
                sql_cmd = new SqlCommand();
                sql_cmd.Connection = sql_con;
                sql_cmd.Parameters.Add("@userId", SqlDbType.Int).Value = UserId;
                sql_cmd.CommandText = "DELETE FROM Accounts WHERE userId = @userId;DELETE FROM AccountsUsers WHERE Id = @userId;";
    
                if (sql_cmd.ExecuteNonQuery() == 1)
                {
                    return true;
                }
                else
                    return false;               
        } 
    

    在 AccountsUsers 之前先从 Accounts 表中删除绝对是最佳实践,因为通常 Accounts 表会对 AccountsUsers 表有一个外部约束。这意味着在 Accounts 中的相应行首先被删除之前,AccountsUsers 中的任何行都不能被删除。

    【讨论】:

    • 是的,但我不明白问题是Steve Mallory告诉是什么
    猜你喜欢
    • 2010-11-17
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多