#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
сказали быть