aqui está uma mesa
create table tq84_virtual_test_without (
col_1 number,
col_2 number,
col_3 number,
col_4 number,
col_5 number
);
com a regra de que col_5
o valor é a soma das outras quatro colunas.
Assim, a tabela é preenchida de acordo:
insert into tq84_virtual_test_without values( 1, 2, 3, 4, 10);
insert into tq84_virtual_test_without values( 3, 8, 7, 5, 23);
commit;
Agora, digamos que seja necessário copiar uma linha e alterar apenas o valor de uma coluna. É claro que isso pode ser feito de maneira bastante elegante (imho, isto é) com uma variável de tipo de linha , assim
declare
r tq84_virtual_test_without%rowtype;
begin
select * into r from tq84_virtual_test_without where col_2 = 8;
r.col_4 := r.col_4 - 2;
r.col_5 := r.col_5 - 2;
insert into tq84_virtual_test_without values r;
end;
/
Isso é elegante porque não sobrecarrega o código-fonte com insert into ... (col_1, col_2...) values (.., ..)
instruções e gostaria de manter esse recurso, se possível.
Por outro lado, col_5
é um candidato perfeito para uma coluna virtual . Então, aqui está quase a mesma coisa, mas col_5
sendo uma coluna virtual:
create table tq84_virtual_test_with (
col_1 number,
col_2 number,
col_3 number,
col_4 number,
col_5 as (col_1 + col_2 + col_3 + col_4) virtual
);
insert into tq84_virtual_test_with values( 1, 2, 3, 4, default);
insert into tq84_virtual_test_with values( 3, 8, 7, 5, default);
commit;
Agora, e isso é lamentável, a seguinte construção não funciona mais:
declare
r tq84_virtual_test_with%rowtype;
begin
select * into r from tq84_virtual_test_with where col_2 = 8;
r.col_4 := r.col_4 - 2;
--
-- ORA-54013: INSERT operation disallowed on virtual columns
--
insert into tq84_virtual_test_with values r;
end;
/
Então, ainda é possível (e em caso afirmativo, como) usar essa variável de tipo de linha junto com colunas virtuais ?
Use uma exibição que exclua as colunas virtuais para fazer a manipulação. Acabei de testar isso e funciona:
Tanto quanto eu posso dizer, esta é a única maneira de contornar sua necessidade de usar %rowtype.
Eu realmente gosto da resposta de Phil (+1). Aqui está uma alternativa que você provavelmente já considerou. Eu o incluo aqui apenas para completar. Ele atende ao seu requisito para um tipo de linha, mas certamente não é tão elegante.
O outro lado dessa moeda é que você pode definir um cursor apenas com as linhas necessárias, mas isso leva a ainda mais código que seria bom evitar.
Embora esta seja uma pergunta antiga, vou postar esta resposta para o futuro:
Se você estiver usando 12c, pode adicionar uma coluna como INVISÍVEL, o que evitará esse problema. Usando isso, você pode continuar usando
%rowtype
, mas a coluna também não aparecerá nasselect *
instruções.Isso pode ser conveniente para colunas adicionadas apenas para desempenho.
Artigo da Oracle sobre colunas invisíveis
Eu recomendaria usar uma tabela para armazenar os dados da tabela e uma exibição para armazenar os resultados calculados desses dados. Misturar os dois em um objeto híbrido apenas confunde a situação para futuros esforços de desenvolvimento.
Um desenvolvedor daqui a cinco anos pode presumir que precisa atualizar todas as colunas da tabela para obter totais precisos. Se, em vez disso, ele estivesse consultando a partir de uma exibição, ele teria que examinar a definição da exibição para atualizar os dados, e a maneira correta de atualizar os dados se tornaria rapidamente aparente.
Colunas virtuais são legais, mas essas coisas devem ser usadas com moderação.