Как удалить данные из двух таблиц в одном запросе

#c# #sql #query-optimization

#c# #sql #оптимизация запросов

Вопрос:

У меня есть две таблицы: Accounts , которая содержит информацию об учетных записях, которые есть у пользователя, и AccountUsers , которая содержит список пользователей, у которых есть учетные записи в вышеупомянутой Accounts таблице.

Если мне нужно удалить пользователя, то мне пришлось бы удалить их из обеих таблиц, где у as AccountUsers будет одна строка этого пользователя, где у as другого может быть много, потому что у одного пользователя может быть много учетных записей.

Я написал следующий код, который хорошо работает и удаляет строку из обеих таблиц, но всякий раз, когда во второй таблице несколько строк, он не удаляет их и 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;
        } 
  

Ответ №1:

В вашем коде есть небольшой логический недостаток. То есть одной записи во второй таблице, Метод executenonquery возвращает 1, но есть более, это будет не вернуть, но какую-то другую цифру. Я бы изменил условие после второго удаления на:

 if (sql_cmd.ExecuteNonQuery() > 1)
  

В связи с этим возникает вопрос — если во второй таблице нет записей, вы хотите, чтобы ваша функция возвращала false?

Комментарии:

1. Это была ошибка, о которой вы сказали. на самом деле он вернул 2, когда удалил две строки и так далее. я никогда не думал об этом, я думал, что есть только 2 значения.0,1

Ответ №2:

Вероятно, вам сначала нужно удалить учетные записи, но не совсем ясно, в каком направлении движется ваш внешний ключ.

Обычно вы не можете удалить данные из двух таблиц в одном запросе, но вы можете выполнить транзакцию и иметь два оператора DELETE в транзакции.

Вы также можете использовать каскадное ограничение удаления, чтобы удалять только из родительской таблицы (но я редко рекомендую это).

Комментарии:

1. В MySQL вы можете. DELETE FROM AccountsUsers, Accounts USING AccountsUsers INNER JOIN Accounts WHERE AccountsUsers.Id = Accounts.userId AND AccountsUsers.Id = @userId

2. в Accounts таблице есть первичный ключ с именем 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;               
    } 
  

Определенно, лучше всего удалять из таблицы Accounts сначала перед AccountsUsers, потому что обычно таблица Accounts будет иметь внешнее ограничение для таблицы AccountsUsers. Это означает, что ни одна строка в AccountsUsers не могла быть удалена до того, как соответствующая строка в Accounts была удалена первой.

Комментарии:

1. Да, работает, но я не понял, проблема была в том, что Steve Mallory сказали быть