Вычесть число из таблицы в SQL
В общем у меня есть таблица с ресурсами золото, дерево, камень, руда и женщины, предположим. Когда я строю мельницу, ну выполняю метод build мельница я хочу чтобы ресурсы из базы данных вычитались, ну минус 10 золота и минус 20 дерева. Ну или нужно больше золота, как сделать так чтобы сколько бы там ни было ресурса, например золота, то вычиталось бы из этой суммы 10, а то у меня получается, что я просто перезаписываю 100 на 10. А чтобы узнать сколько у меня сейчас в таблице золота я должен выполнить ешё один запрос и потом уже получив 100 я вычту 10, это любой дурак сможет, а вот как сделать, чтобы в базу данных уходил statment что мол вычти ка 10 из таблицы, а если что пойдёт не так, ты мол просигналь, что нужно золота больше, можно ли такое диво сотворить?
connectionString = ConfigurationManager.ConnectionStrings["SQLConnection"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString.ToString());
con.Open();
string sql = $@"SELECT [Wood]
FROM [GG].[dbo].[Villages]
where OwnerUser = '{user.Name}' and Name = '{user.Village}'";
SqlCommand cmd = new SqlCommand(sql, con);
int amount = (int)cmd.ExecuteScalar();
string sql1 = $@"Update [GG].[dbo].[Villages]
SET Wood = '{amount - wood}'
WHERE OwnerUser = '{user.Name}' and Name = '{user.Village}'; ";
SqlCommand cmd1 = new SqlCommand(sql1, con);
cmd1.ExecuteNonQuery();
con.Close();
Ответы (1 шт):
Не нужно предварительно считывать значение из БД, если нужно просто изменить его.
В запросе UPDATE можно указать формулу изменения: SET Wood = Wood - @amount.
using (SqlConnection con = new SqlConnection(_connectionString))
{
con.Open();
string updateSql = @"
UPDATE [GG].[dbo].[Villages]
SET [Wood] = [Wood] - @amount
WHERE [OwnerUser] = @name and [Name] = @village";
using (SqlCommand cmd = new SqlCommand(updateSql, con))
{
cmd.Parameters.Add("amount", SqlDbType.Int).Value = amount;
cmd.Parameters.Add("name", SqlDbType.NVarChar).Value = user.Name;
cmd.Parameters.Add("village", SqlDbType.NVarChar).Value = user.Village;
int rowsAffected = cmd.ExecuteNonQuery();
}
}
Не следует строку соединения получать каждый раз при вызове метода. Задайте её один раз в конструкторе класса полю и далее используйте его.
Обязательно освобождайте ресурсы, оборачивая их в using.
Используйте параметризованные запросы. Это защитит от sql-инъекций и увеличит производительность.
Я не знаю, какие именно типы в таблице, поэтому замените SqlDbType.Int, SqlDbType.NVarChar на правильные.
Если при этом необходимо обеспечить, чтобы количество ресурса не ушло в минус, можно наложить ограничение (constraint) на колонку таблицы.
create table Villages (
-- другие колонки
Wood int check (Wood > 0)
)
CHECK Constraints
Create Check Constraints
Во время выполнения запрос СУБД выбросит сообщение об ошибке. В коде C# нужно обработать исключение:
try
{
int rowsAffected = cmd.ExecuteNonQuery();
}
catch (System.Data.SqlClient.SqlException e)
{
// Мало дерева!
}