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 / 44215
Accepted
Jack Douglas
Jack Douglas
Asked: 2013-06-11 07:25:19 +0800 CST2013-06-11 07:25:19 +0800 CST 2013-06-11 07:25:19 +0800 CST

Como combinar as operações `delete` e `insert` em uma instrução?

  • 772

para os dados a seguir, gostaria de poder deletar algumas linhas e inserir outras dando o resultado abaixo. Isso é possível com uma única instrução (por exemplo, com a mergeinstrução)?

create table product(product_id integer primary key);
insert into product(product_id) values(1);
insert into product(product_id) values(2);
insert into product(product_id) values(3);

create table split( parent_id integer not null references product, 
                    child_id integer not null references product,
                    primary key(parent_id, child_id) );

insert into split(parent_id, child_id) values(1,2);
insert into split(parent_id, child_id) values(1,3);

create table sale(sale_at date, product_id integer references product);

insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 1);
insert into sale(sale_at, product_id) values(sysdate, 2);
insert into sale(sale_at, product_id) values(sysdate, 2);

 

select sale_at, product_id from sale where product_id not in (select parent_id from split)
union all
select sale_at, child_id from sale join split on(parent_id=product_id);

/*
|                     SALE_AT | PRODUCT_ID |
--------------------------------------------
| June, 10 2013 15:18:22+0000 |          2 |
| June, 10 2013 15:18:22+0000 |          2 |
| June, 10 2013 15:18:22+0000 |          3 |
| June, 10 2013 15:18:22+0000 |          2 |
| June, 10 2013 15:18:22+0000 |          3 |
| June, 10 2013 15:18:22+0000 |          2 |
| June, 10 2013 15:18:22+0000 |          3 |
| June, 10 2013 15:18:22+0000 |          2 |
*/

( SQLFiddle )

----editar:

para esclarecer, o efeito que estou tentando obter com uma única mergedeclaração é este:

insert into sale(sale_at, product_id)
select sale_at, child_id from sale join split on parent_id=product_id;

delete from sale where product_id in (select parent_id from split);

e o motivo pelo qual gostaria de uma solução de instrução única é evitar uma condição de corrida em que outra transação insere/confirma dados entre inserte deletena transação principal.

oracle oracle-11g-r2
  • 1 1 respostas
  • 21767 Views

1 respostas

  • Voted
  1. Best Answer
    Vincent Malgrat
    2013-06-12T06:42:00+08:002013-06-12T06:42:00+08:00

    Você pode fazer isso de uma só vez, mais ou menos:

    SQL> MERGE INTO sale s
      2  USING (SELECT ROWID rid, sale_at, product_id
      3           FROM sale
      4          WHERE product_id IN (SELECT parent_id FROM split)
      5         UNION ALL
      6         SELECT CAST (NULL AS ROWID) rid, sale_at, child_id FROM sale
      7           JOIN split ON (parent_id = product_id)) m
      8  ON (s.ROWID = m.rid)
      9  WHEN MATCHED THEN
     10     UPDATE SET s.sale_at = m.sale_at
     11     DELETE WHERE 1 = 1
     12  WHEN NOT MATCHED THEN
     13     INSERT VALUES (m.sale_at, m.product_id);
    
    Done
    
    SQL> select * from sale;
    
    SALE_AT                                  PRODUCT_ID
    ----------- ---------------------------------------
    11/06/2013                                        2
    11/06/2013                                        2
    11/06/2013                                        3
    11/06/2013                                        3
    11/06/2013                                        3
    11/06/2013                                        2
    11/06/2013                                        2
    11/06/2013                                        2
    

    Isso excluirá as linhas da venda que estão presentes na divisão e as substituirá pelos produtos divididos apropriados.

    Você também pode escrever:

    SQL> MERGE INTO sale s
      2  USING (SELECT CASE WHEN row_number() over (PARTITION BY s.rowid
      3                                             ORDER BY sp.rowid) = 1
      4                     THEN  s.rowid
      5                END rid,
      6                s.sale_at, sp.parent_id, sp.child_id
      7           FROM split sp
      8           JOIN sale s
      9             ON sp.parent_id = s.product_id) m
     10  ON (s.rowid = m.rid)
     11  WHEN MATCHED THEN UPDATE SET s.product_id = m.child_id
     12  WHEN NOT MATCHED THEN INSERT VALUES (m.sale_at, m.child_id);
    

    Aqui a linha em venda será substituída (atualizada) por seu primeiro componente dividido e os componentes adicionais serão inseridos.

    • 10

relate perguntas

  • Backups de banco de dados no Oracle - Exportar o banco de dados ou usar outras ferramentas?

  • ORDER BY usando prioridades personalizadas para colunas de texto

  • Interface sqlplus confortável? [fechado]

  • Como encontrar as instruções SQL mais recentes no banco de dados?

  • Como posso consultar nomes usando expressões regulares?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • 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

    Conceder acesso a todas as tabelas para um usuário

    • 5 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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