As tabelas temporárias globais do Oracle não são objetos transitórios. São tabelas de heap adequadas. Nós os criamos uma vez e qualquer sessão pode usá-los para armazenar dados visíveis apenas para essa sessão .
O aspecto temporário é que os dados não são persistentes além de uma transação ou uma sessão. O detalhe chave da implementação é que os dados são gravados em um tablespace temporário e não permanente. No entanto, os dados ainda são gravados e lidos no disco, portanto, há uma sobrecarga notável no uso de tabelas temporárias globais.
O ponto é que não devemos descartar e recriar tabelas temporárias. Se você estiver tentando portar a lógica de estilo do SQL Server para o Oracle, considere o uso de coleções PL/SQL para manter dados temporários na memória. Descubra mais.
A causa específica de
ORA-14452
é que não podemos descartar uma tabela temporária global que tenha persistência no escopo da sessão se ela contiver dados durante a sessão. Mesmo que a mesa esteja vazia no momento... SQL> create global temporary table gtt23 (col1 number)
2 on commit preserve rows
3 /
Table created.
SQL> insert into gtt23 values (1);
1 row created.
SQL> commit;
Commit complete.
SQL> delete from gtt23;
1 row deleted.
SQL> commit;
Commit complete.
SQL> drop table gtt23;
drop table gtt23
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
SQL>
A solução é encerrar a sessão e reconectar, ou (um tanto bizarra) truncar a tabela e depois eliminá-la.
SQL> truncate table gtt23;
Table truncated.
SQL> drop table gtt23;
Table dropped.
SQL>
Se alguma outra sessão estiver usando a tabela temporária global - e isso é possível (daí o global nomenclature) então você não poderá descartar a tabela até que todas as sessões se desconectem.
Portanto, a solução real é aprender a usar as tabelas temporárias globais corretamente:crie tabelas temporárias globais específicas para corresponder a cada relatório. Ou, como eu disse, use coleções PL/SQL. Ou, ainda, apenas aprenda a escrever SQL bem ajustado. Muitas vezes usamos tabelas temporárias como uma solução para uma consulta mal escrita que pode ser salva com um caminho de acesso melhor.
Tendo examinado seu código completo, o fluxo parece ainda mais bizarro:
- Solte e recrie uma tabela temporária global
- Preencher tabela temporária
- Selecione da tabela temporária para o array PL/SQL
- Inserir na tabela real usando a inserção em massa da matriz PL/SQL
Há tanta sobrecarga e atividade desperdiçada aqui. Tudo o que você precisa fazer é pegar os dados inseridos em
v2d_temp
e preencha diretamente vertical_design
, de preferência com uma instrução INSERT INTO ... SELECT * FROM. Você precisará de algum pré-processamento para converter uma matriz JSON em uma consulta, mas isso é fácil de conseguir em Java ou PL/SQL. Parece-me certo que as tabelas temporárias globais não são a solução certa para o seu cenário.
"nosso chefe ou outras pessoas persistem em fazer algo do jeito deles, então você não pode mudar isso"
O que você tem é um problema do chefe não é um problema de programação . Consequentemente, é fora do tópico no que diz respeito ao StackOverflow. Mas aqui estão algumas sugestões de qualquer maneira.
A principal coisa a lembrar é que não estamos falando de um compromisso em alguma arquitetura abaixo do ideal:o que seu chefe propõe claramente não funcionará em um ambiente multiusuário. então, suas opções são:
- Ignore o
ORA-14452
erro, prossiga para a produção e, em seguida, use a defesa "mas você me disse para" quando tudo der terrivelmente errado. Esta é a jogada mais fraca. - Destrua secretamente as tabelas globais e implemente algo que funcione em um cenário multiusuário. Isso é de alto risco porque você não tem defesa se falhar na implementação.
- Fale com seu chefe. Diga a eles que você está se deparando com o
ORA-14452
erro, digamos que você fez alguma investigação e parece um problema fundamental com o uso de tabelas temporárias globais dessa maneira, mas obviamente você ignorou algo. Em seguida, pergunte como eles contornaram esse problema quando já o implementaram antes. Isso pode acontecer de várias maneiras, talvez eles tenham uma solução alternativa, talvez eles percebam que essa é a maneira errada de usar tabelas temporárias globais, talvez eles digam para você se perder. De qualquer forma, esta é a melhor abordagem:você levantou as preocupações para o nível apropriado.
Boa sorte.