confusão sobre o uso de tipos em vez de gtts no Oracle
Pergunta
Estou tentando converter consultas como abaixo em tipos para não precisar usar GTT:
insert into my_gtt_table_1
(house, lname, fname, MI, fullname, dob)
(select house, lname, fname, MI, fullname, dob
from (select 'REG' house, mbr_last_name lname, mbr_first_name fname, mbr_mi MI,
mbr_first_name || mbr_mi || mbr_last_name fullname, mbr_dob dob from
table_1 a, table_b
where a.head = b.head and mbr_number = '01' and mbr_last_name = v_last_name) c
acima é apenas um exemplo, mas consultas complexas são maiores que isso.
o acima está dentro de um procedimento armazenado.Então, para evitar o gtt (my_gtt_table_1).Eu fiz o seguinte:
create or replace type lname_row as object
(
house varchar2(30)
lname varchar2(30),
fname varchar2(30),
MI char(1),
fullname VARCHAR2(63),
dob DATE
)
create or replace type lname_exact as table of lname_row
Agora em SP:
type lname_exact is table of <what_table_should_i_put_here>%rowtype;
tab_a_recs lname_exact;
Acima, não tenho certeza de qual tabela colocar, pois minha consulta possui subconsultas aninhadas.
consulta no SP:(Estou tentando isso como exemplo para ver se funciona)
select lname_row('',
'',
'',
'',
'',
'',
sysdate) bulk collect
into tab_a_recs
from table_1;
Estou recebendo erros como:ORA-00913:muitos valores
Estou realmente confuso e preso com isso :(
Solução
Você definiu um tipo com 6 atributos e você tenta instanciá-lo com 7 valores.Em vez disso, tente isto:
select lname_row(/*'',*/
'',
'',
'',
'',
'',
sysdate) bulk collect
into tab_a_recs
from table_1;
EditarTambém parece haver uma confusão em relação aos tipos.No Oracle você pode definir tipos em SQL ou em PL/SQL.Os tipos SQL são acessíveis ao SQL (!), enquanto os PL/SQL oferecem alguns recursos extras, mas são invisíveis ao SQL puro (o PL/SQL também pode acessar os tipos SQL).
Dito isto, é confuso e imprudente nomear os tipos da mesma forma tanto em SQL quanto em PL/SQL (você se depara com sombreamento problemas).Você definiu o lname_exact
digite duas vezes (com seu CREATE STATEMENT e em seu bloco DECLARE).Como você está instanciando um lname_exact
em uma instrução SQL, o tipo escolhido neste caso é o tipo SQL (com apenas 6 atributos).
Você deve remover a declaração de lname_exact
no SP ou renomeá-lo.
Outras dicas
Além da excelente resposta de Vincent: você não precisa criar explicitamente um LNAME_ROW na sua consulta SQL. A coleta em massa corresponderá automaticamente às colunas selecionadas com os campos do alvo interno. Então, com base no que você mostrou até agora, não precisa criar tipos no nível do esquema, basta defini -los no seu bloco PL/SQL.
Aqui está um exemplo simples que funciona:
SQL> l
1 declare
2 type my_row is record (x number, y date);
3 type my_tab is table of my_row;
4 a_table my_tab;
5 begin
6 select 1,sysdate
7 bulk collect into a_table
8 from dual;
9 dbms_output.put_line(a_table(1).y);
10* end;
SQL> /
14-JUN-10