SQL como aumentar ou diminuir um para uma coluna interna em um comando

119

Eu tenho uma tabela Pedidos que possui uma coluna Quantidade. Durante o check in ou check out, precisamos atualizar a coluna Quantidade por um. Existe uma maneira de fazer isso em uma ação ou temos que obter o valor existente e, em seguida, adicionar ou menos um em cima dele?

Outra questão é quando inserimos uma nova linha, precisamos verificar se os mesmos dados existem e, em seguida, inserir se não, que são duas etapas, ou existe uma maneira melhor de fazer isso?

obrigado,

5YrsLaterDBA
fonte

Respostas:

250

Para responder ao primeiro:

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

Para responder à segunda:

Existem várias maneiras de fazer isso. Como você não especificou um banco de dados, assumirei o 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

Ambos podem lidar com sua pergunta. No entanto, a primeira sintaxe permite mais flexibilidade para atualizar o registro em vez de apenas substituí-lo (como faz a segunda).

Tenha em mente que para que ambos existam, deve haver uma chave ÚNICA definida ...

gahooa
fonte
32
Visto que você não especificou um banco de dados, você realmente deve assumir o SQL padrão.
paxdiablo
12

A resposta em uma única etapa para a primeira pergunta é usar algo como:

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

Essa é uma maneira de fazer isso com uma única instrução.

Quanto à segunda pergunta, você não deve precisar recorrer à ginástica SQL específica do DBMS (como UPSERT) para obter o resultado desejado. Existe um método padrão para atualizar ou inserir que não requer um DBMS específico.

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

Ou seja, você tenta fazer a criação primeiro. Se já estiver lá, ignore o erro. Caso contrário, você o cria com um valor 0.

Em seguida, faça a atualização que funcionará corretamente se:

  • a linha existia originalmente.
  • alguém o atualizou entre sua inserção e atualização.

Não é uma única instrução e ainda, surpreendentemente, é como temos feito isso com sucesso por muito tempo.

paxdiablo
fonte
4

Se meu entendimento estiver correto, as atualizações devem ser bem simples. Eu apenas faria o seguinte.

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

Você pode precisar de filtros adicionais para atualizar apenas uma única linha em vez de todas as linhas.

Para inserções, você pode armazenar em cache algum id exclusivo relacionado ao seu registro localmente, verificar nesse cache e decidir se deseja inserir ou não. A abordagem alternativa é sempre inserir e verificar se há erros de violação de PK e ignorar, uma vez que esta é uma inserção redundante.

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

Pelo que eu sei, não há suporte integrado para INSERT-OR-UPDATE no SQL. Eu sugiro criar um procedimento armazenado ou usar uma consulta condicional para conseguir isso. Aqui você pode encontrar uma coleção de soluções para diferentes bancos de dados.

Daniel Brückner
fonte
Você pode obter um erro de sintaxe
usando
0

para responder a segunda:

torne a coluna exclusiva e capture a exceção se ela estiver definida com o mesmo valor.

dotjoe
fonte
0

@dotjoe É mais barato atualizar e verificar @@ rowcount, faça uma inserção após o fato.

As exceções são caras e as atualizações são mais frequentes

Sugestão: Se você quiser ter um ótimo desempenho em seu DAL, faça com que o front end passe um ID exclusivo para a linha a ser atualizada, se inserir nulo.

Os DALs devem ser CRUD e não precisam se preocupar em não ter estado.

Se você torná-lo sem estado, com bons índices, você não verá uma diferença com a seguinte instrução SQL vs 1. IF (selecione o primeiro * formulário x onde PK = @ ID) Insira outra atualização

brian chandley
fonte