AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 116615
Accepted
Rainbolt
Rainbolt
Asked: 2015-10-01 07:38:21 +0800 CST2015-10-01 07:38:21 +0800 CST 2015-10-01 07:38:21 +0800 CST

Como posso evitar a repetição da mesma condição em uma cláusula "quando correspondido, então atualize"?

  • 772

Eu quero mesclar uma tabela em outra. Preciso aplicar a lógica condicional na minha cláusula WHEN MATCHED, que idealmente seria feita assim:

MERGE INTO ATable AS a
USING BTable AS b
ON a.ID = b.ID
WHEN NOT MATCHED THEN
-- Do insert
WHEN MATCHED AND b.NeedsAdjustment = 1 THEN
UPDATE SET
    Col1 = b.Col1 + b.Adjustment
    ,Col2 = b.Col2 + b.Adjustment
    ,Col3 = b.Col3 + b.Adjustment
WHEN MATCHED THEN -- Default case (b.NeedsAdjustment <> 1)
UPDATE SET
    Col1 = b.Col1
    ,Col2 = b.Col2
    ,Col3 = b.Col3

Este não é um SQL válido. De acordo com a documentação do MSDN:

Se houver duas cláusulas WHEN MATCHED, uma deverá especificar uma ação UPDATE e a outra deverá especificar uma ação DELETE.

Isso me leva à seguinte consulta:

MERGE INTO ATable AS a
USING BTable AS b
ON a.ID = b.ID
WHEN NOT MATCHED THEN
-- Insert happens here
WHEN MATCHED THEN
UPDATE SET
    Col1 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col1 ELSE b.Col1 + b.Adjustment END
    ,Col2 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col2 ELSE b.Col2 + b.Adjustment END
    ,Col3 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col3 ELSE b.Col3 + b.Adjustment END

A lógica condicional é movida dentro da atualização para contornar o fato de que as mesclagens podem ter apenas uma WHEN MATCHED THEN UPDATEcláusula. Agora, em vez de uma verificação por linha, tenho uma verificação por linha por coluna (e há muito mais colunas do que as três do exemplo).

Posso evitar repetir essa condição para cada coluna que precisa ser atualizada? Existe uma maneira melhor de fazer atualizações condicionais que talvez não envolvam mesclagens?

sql-server update
  • 4 4 respostas
  • 1991 Views

4 respostas

  • Voted
  1. Zane
    2015-10-01T09:08:44+08:002015-10-01T09:08:44+08:00

    Eu recomendaria simplesmente evitar MERGEem primeiro lugar por todos os motivos listados aqui e simplesmente usar uma instrução de atualização padrão.

    UPDATE A 
    SET
        Col1 = b.Col1 + b.Adjustment
        ,Col2 = b.Col2 + b.Adjustment
        ,Col3 = b.Col3 + b.Adjustment
    FROM ATable as A
    inner Join TableB as B
        ON a.ID = b.ID
        AND b.NeedsAdjustment = 1
    ;
    UPDATE A 
    SET
        Col1 = b.Col1 
        ,Col2 = b.Col2
        ,Col3 = b.Col3
    FROM ATable as A
    inner Join TableB as B
        ON a.ID = b.ID
    AND b.NeedsAdjustment <> 1
    --Or INSNUL(NeedsAdjustment,0) If it's a nullable column
    ;
    

    A longo prazo, essa seria uma abordagem mais estável do que usar MERGE. Eu também adicionei o <>porque, se não estiver lá, você UPDATEsubstituirá o primeiro arquivo UPDATE.

    • 7
  2. Best Answer
    Dave
    2015-10-01T08:57:02+08:002015-10-01T08:57:02+08:00

    MERGEé uma declaração útil, mas limitada em situações como esta. Sugiro simplesmente separar sua consulta para que você possa cobrir completamente sua lógica. Se você esperava ou exigia o fato de que a MERGEinstrução realizará suas operações em uma única transação, você pode declarar uma transação explícita em torno de sua lógica:

    BEGIN TRAN
    INSERT
    WHERE
    
    UPDATE
    WHERE
    
    UPDATE
    WHERE
    
    COMMIT TRAN
    
    • 4
  3. Andriy M
    2015-10-01T10:23:56+08:002015-10-01T10:23:56+08:00

    Se NeedsAdjustmentfor uma bitcoluna ou se for uma coluna inteira que só pode ter valores 0 ou 1, você pode usar uma única instrução UPDATE como esta para cobrir os dois casos:

    UPDATE
      a
    SET
      a.Col1 = b.Col1 + b.NeedsAdjustment * b.Adjustment,
      a.Col2 = b.Col2 + b.NeedsAdjustment * b.Adjustment,
      a.Col3 = b.Col3 + b.NeedsAdjustment * b.Adjustment
    FROM
      dbo.ATable AS a
      INNER JOIN dbo.BTable AS b ON a.ID = b.ID
    ;
    

    Se a coluna for anulável, aplique adicionalmente ISNULL ou COALESCE:

    …
    SET
      a.Col1 = b.Col1 + ISNULL(b.NeedsAdjustment, 0) * b.Adjustment,
      a.Col2 = b.Col2 + ISNULL(b.NeedsAdjustment, 0) * b.Adjustment,
      a.Col3 = b.Col3 + ISNULL(b.NeedsAdjustment, 0) * b.Adjustment
    …
    
    • 4
  4. madreflection
    2015-10-01T10:52:45+08:002015-10-01T10:52:45+08:00

    Usando um CTE, você pode "preparar" os dados que estão BTablepara poder usá-los uniformemente na instrução MERGE. Nesse caso, se uma linha não precisar ser ajustada, altere o Ajuste para zero.

    WITH b (Col1, Col2, Col3, Adjustment)
    AS
    (
        SELECT Col1, Col2, Col3, CASE WHEN NeedsAdjustment = 1 THEN Adjustment ELSE 0 END
        FROM BTable
    )
    MERGE INTO ATable AS a
    USING b
        ON a.ID = b.ID
    WHEN NOT MATCHED THEN
        -- Insert happens here
    WHEN MATCHED THEN
        UPDATE SET
            Col1 = b.Col1 + b.Adjustment,
            Col2 = b.Col2 + b.Adjustment,
            Col3 = b.Col3 + b.Adjustment;
    
    • 4

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve