Tabela sem PK. Como identificar as linhas ?

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
rnovais
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 1
Registrado em: Ter, 05 Set 2006 3:22 pm
Localização: são paulo - sp

Seguinte... tenho algumas tabelas onde não existe nenhuma coluna que identifique os registros. O problema é que eu
não posso alterar a tabela para ascrecentar uma coluna, e pretendo pegar alguns registros a cada 10 minutos
para jogar em uma outra tabela, como não tenho nenhuma coluna que identique o registro já selecionado antes gostaria
de saber se alguém tem algum truque que possa me ajudar.

Att,

Ricardo
hitchhiker
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 1
Registrado em: Ter, 05 Set 2006 11:15 pm
Localização: poa

crie uma nova tabela com as mesmas colunas da original + uma coluna de identificador.
Crie uma trigger AFTER INSERT na tabela original, inserindo um registro na nova tabela.

Agora é só trabalhar sempre com a nova tabela, que possui PK... foi a única gambiarra em que pensei...
NiNo
Rank: Programador Sênior
Rank: Programador Sênior
Mensagens: 62
Registrado em: Seg, 11 Jul 2005 2:03 pm
Localização: são Paulo
NiNo
Developer

Todo e qualquer registro no Oracle possui um ROWID (pseudo coluna), que é um número em formato HEXA e unico para cada registro de dados do banco, este registro será somente alterado se o registro for deletado e incluido novamente. Em procedimentos de UPDATE o seu conteudo não é alterado. Em procedimentos de DELETE ele desaparece. Em procedimentos de INSERT ele é criado.
Nota: Esta identificação é gerada pelo banco, você não tem controle sobre a mesma.

Espero ter ajudado.
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Pelo que eu sei, não é confiável você fazer referência por ROWID.
Algum DBA poderia explicar se minha afirmação é verdadeira ou falsa? :?
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Dr. Gori,

Acho que é isto o que procurava:


Listagem 2 - Consulta utilizando o ROWID


Esta busca somente acontece se alguma das colunas acessadas não estiver presente no índice. Se todas as colunas acessadas estiverem presentes no índice, então o acesso pelo ROWID não se torna necessário.
Apesar de ser a forma mais rápida de acesso aos dados, não é recomendado que os desenvolvedores utilizem esta forma de acesso diretamente. O ROWID é uma informação interna do Oracle, podendo ser de modificado através de algumas operações de administração do banco de dados, como importação e exportação das tabelas.


Fonte: http://www.linhadecodigo.com.br/artigos.asp?id_ac=768
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Mandou bem!
O ROWID até pode ser usado pra referenciar uma linha quando vai se usar a informação "rapidinho" (logo após buscar o rowid).

Isso porque nesse meio tempo sabemos que não haverá mudança de base, de tablespace, etc... ou seja, não afetará o rowid da linha. Caso se armazene um ROWID pra futuras consultas, talvez algo mudou na base e você estará acessando outra linha.
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Valeu Dr Gori.

Devido à isso, deixou aqui uma opinião para que os demais aqui tb opinem:

1) Criar a nova tabela, com uma coluna que irá servir de PK;
2) Exportar os dados para Nova Tabela;
3) Definir a PK;
HenriqueMachado
Rank: Programador Sênior
Rank: Programador Sênior
Mensagens: 48
Registrado em: Seg, 29 Mai 2006 1:24 pm
Localização: Blumenau - SC
Abraços,
Henrique Machado Muller

Bom gente voltando ao assundo de ROWID.

Tenho uma tabela com pk de 5 campos.
Preciso fazer uma trigger para disparar quando da um insert nessa tabela, dai essa trigger insere em um Type de uma package temporariamente o ROWID. e depois (after segmente) eu trabalho com esse ROWID.

Bom o que estou com medo é que na hora de pesquizer por esse ROWID o hexa mudou, será que tem chance de acontecer.

Vou dar um resumo dos codigos

Selecionar tudo

CREATE OR REPLACE TRIGGER TG_AFTER_I_GISS_BOLETOS
  AFTER INSERT 
  ON GISSONLINE.TB_INTER_BOLETOS_GISS  
  REFERENCING NEW AS NEW OLD AS OLD
  FOR EACH ROW  
BEGIN
  PK_GISSONLINE.adicionaRegistro(:NEW.ROWID,
                                 'TB_INTER_BOLETOS_GISS',
                                 'INSERT');  
END TG_AFTER_I_GISS_BOLETOS;

Selecionar tudo

CREATE OR REPLACE TRIGGER TG_AFTER_I_GISS_BOLETOS
  AFTER INSERT 
  ON GISSONLINE.TB_INTER_BOLETOS_GISS  
BEGIN
  PK_GISSONLINE.processaRegistros();  
END TG_AFTER_I_GISS_BOLETOS;
e na PK_GISSONLINE (uma package) [...] significa que existe mais codigo, mais não importante para a pergunta em questão.

Selecionar tudo

CREATE OR REPLACE PACKAGE BODY PK_GISSONLINE IS
[...]
  TYPE tp_change_rec IS RECORD(
     ChaveROWID     ROWID
    ,TableName VARCHAR2(30)
    ,Acao      VARCHAR2(30));

  TYPE tp_change_tab IS TABLE OF tp_change_rec;
  gChangeTab tp_change_tab := tp_change_tab();
  PROCEDURE adicionaRegistro(PChave NUMBER
                            ,PTable VARCHAR2
                            ,PAcao  VARCHAR2) IS
  BEGIN
    IF USER = 'SIATUBLU' THEN
      gChangeTab.EXTEND();
      gChangeTab(gChangeTab.LAST).Chave := PChave;
      gChangeTab(gChangeTab.LAST).TableName := PTable;
      gChangeTab(gChangeTab.LAST).Acao := PAcao;
    END IF;
  END adicionaRegistro;

  PROCEDURE processaRegistros IS
    i NUMBER;
  BEGIN
    IF USER = 'SIATUBLU' THEN
    -- procedure responsável apenas para chamada de outras procedures, conforme situação encrontada
    IF gChangeTab.COUNT > 0 THEN
      FOR i IN gChangeTab.FIRST .. gChangeTab.LAST LOOP
        IF gChangeTab(i).Acao = 'INSERT' THEN
        
          IF gChangeTab(i).TableName = 'TB_INTER_BOLETOS_GISS' THEN
            for rg in (select * from TB_INTER_BOLETOS_GISS' where rowid = gChangeTab(i).ChaveRowID) loop
              -- processamento das informações[...]
            end loop;
          END IF;
        END IF;
     END LOOP;
   END IF;
END processaRegistros ; 
[...]
HenriqueMachado
Rank: Programador Sênior
Rank: Programador Sênior
Mensagens: 48
Registrado em: Seg, 29 Mai 2006 1:24 pm
Localização: Blumenau - SC
Abraços,
Henrique Machado Muller

Outra coisa pessoal.
Como eu guardo o ROWID em uma variavel que o codigo acima não funcionou.
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Eu já vi por aí o TO_ROWID, que deixa a uma variável do tipo caracter para o tipo rowid.
As vezes dá umas incompatibilidade de tipos. Tenta usar o TO_ROWID. E se não funcionar, mostra pra gente qual erro está dando.
HenriqueMachado
Rank: Programador Sênior
Rank: Programador Sênior
Mensagens: 48
Registrado em: Seg, 29 Mai 2006 1:24 pm
Localização: Blumenau - SC
Abraços,
Henrique Machado Muller

obrigado dr_gori.

Mais acabei descrobindo qual era o erro no package.
O nome ROWID não poderia ser usado para uma variavel
foi só colocar

ChaveROWID ROWID;

como no exemplo abaixo

Selecionar tudo

declare
  TYPE tprec IS RECORD(
     AROWID rowid
    ,TableName VARCHAR2(30));

  TYPE tp_change_tab IS TABLE OF tprec INDEX BY BINARY_INTEGER;
  gChangeTab tp_change_tab;
		i integer;
begin
  i := 1;
 for rg in (select rowid , descricao from logradouro where rownum <= 10 ) loop
	  gChangeTab(i).AROWID := rg.rowid;
			dbms_output.put_line(i || ':' || rg.rowid ||':' || rg.descricao);
			i := 1 + i;
	end loop;
	dbms_output.put_line(LPAD('-',50,'-'));
	for x in gChangeTab.first .. gChangeTab.last loop
			for rg in (select * from logradouro where rowid = gChangeTab(x).AROWID) loop
  			dbms_output.put_line(x || ':' || gChangeTab(x).AROWID ||':' || rg.descricao);
			end loop;
	end loop;
end;
sandkiller
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Seg, 12 Mai 2008 1:44 pm
Localização: Poços de Caldas

Ou fazer assim:

Selecionar tudo

DECLARE
   L_rowid rowid;
BEGIN
   INSERT INTO tabela(<colunas>)
   VALUES (<valores>) RETURN ROWID INTO L_rowid;
   
   ...
EXCEPTION
   ...
END;
Avatar do usuário
Toad
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 253
Registrado em: Sex, 18 Nov 2005 2:14 pm
Localização: Seattle, WA
Contato:
Matheus Gonçalves
matheus.dev
twitter.com/developer__c

É, eu criaria a tabela nova com sua própria PK, mas deve-se tomar cuidado, pois pode ocorrer inconsistência:

Situação 1:

Dados da tabela mãe:

Selecionar tudo

nome       idade    telefone
Alfredo       35    1234-5678
Ricardo       35    1234-5678
Dados da nova tabela:

Selecionar tudo

cod	nome		idade	telefone
1	Alfredo		35   	1234-5678
2	Ricardo		35   	1234-5678
Imagine agora que você, na tabela mãe, mude o nome de Ricardo, para Alfredo... como alterar o registro na tabela filha? Você teria que fazer uma verificação antes da alteração, qual é o registro na filha, efetuar a alteração e só então alterar o registro na tabela mãe...

Dá pra fazer, mas vai dar trabalho.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 17 visitantes