SQL, как увеличить или уменьшить один для столбца int за одну команду


119

У меня есть таблица заказов, в которой есть столбец количества. Во время регистрации заезда или выезда нам необходимо обновить столбец «Количество» на единицу. Есть ли способ сделать это за одно действие или нам нужно получить существующее значение, а затем добавить или минус один поверх него?

Другой вопрос: когда мы вставляем новую строку, нужно ли нам проверять, существуют ли те же данные, а затем вставлять, если нет, что составляет два шага, или есть лучший способ сделать это?

Спасибо,

Ответы:


250

Чтобы ответить на первый:

UPDATE Orders SET Quantity = Quantity + 1 WHERE ...

Чтобы ответить на второй:

Есть несколько способов сделать это. Поскольку вы не указали базу данных, я буду использовать MySQL.

  1. INSERT INTO table SET x=1, y=2 ON DUPLICATE KEY UPDATE x=x+1, y=y+2
  2. REPLACE INTO table SET x=1, y=2

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

Имейте в виду, что для существования обоих должен быть определен УНИКАЛЬНЫЙ ключ ...


32
Поскольку вы не указали базу данных, вам действительно стоит использовать стандартный SQL.
paxdiablo

12

Одношаговый ответ на первый вопрос - использовать что-то вроде:

update TBL set CLM = CLM + 1 where key = 'KEY'

Это очень простой способ сделать это с помощью одной инструкции.

Что касается второго вопроса, вам не нужно прибегать к специальной SQL-гимнастике СУБД (например, UPSERT), чтобы получить желаемый результат. Существует стандартный метод обновления или вставки, который не требует конкретной СУБД.

try:
    insert into TBL (key,val) values ('xyz',0)
catch:
    do nothing
update TBL set val = val + 1 where key = 'xyz'

То есть вы сначала пытаетесь сделать творение. Если он уже там, игнорируйте ошибку. В противном случае вы создаете его со значением 0.

Затем выполните обновление, которое будет работать правильно независимо от того:

  • строка изначально существовала.
  • кто-то обновил его между вашей вставкой и обновлением.

Это не единичная инструкция, и все же, как ни странно, так мы успешно ее выполняем уже долгое время.


4

Если я правильно понимаю, обновления должны быть довольно простыми. Я бы сделал следующее.

UPDATE TABLE SET QUANTITY = QUANTITY + 1 and
UPDATE TABLE SET QUANTITY = QUANTITY - 1 where QUANTITY > 0

Вам могут понадобиться дополнительные фильтры, чтобы просто обновить одну строку, а не все строки.

Для вставок вы можете локально кэшировать некоторый уникальный идентификатор, связанный с вашей записью, и проверять этот кеш и решать, вставлять или нет. Альтернативный подход - всегда вставлять и проверять наличие ошибки нарушения PK и игнорировать, поскольку это избыточная вставка.


4
UPDATE Orders Order
SET Order.Quantity =  Order.Quantity - 1
WHERE SomeCondition(Order)

Насколько мне известно, в SQL нет встроенной поддержки INSERT-OR-UPDATE. Я предлагаю создать хранимую процедуру или использовать условный запрос, чтобы добиться этого. Здесь вы можете найти коллекцию решений для разных баз данных.


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

0

чтобы ответить на второй:

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


0

@dotjoe Дешевле обновлять и проверять @@ rowcount, делать вставку постфактум.

Исключения дорогие && обновления происходят чаще

Предложение: если вы хотите быть сверхэффективным в своем DAL, сделайте передний конец уникальным идентификатором для обновляемой строки, если вставка null.

DAL должны быть CRUD, и не нужно беспокоиться о том, что они не имеют состояния.

Если вы сделаете его без сохранения состояния, с хорошими индексами вы не увидите различий со следующим оператором SQL vs 1. ЕСЛИ (выберите верхний 1 * форма x, где PK = @ ID) Вставить другое обновление

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.