Pular para o conteúdo
Visualizando 6 posts - 1 até 6 (de 6 do total)
  • Autor
    Posts
  • #97636
    gsmdf
    Participante

      Olá,

      Preciso da tabela e do campo que tenha o texto inteiro de triggers do banco e não linha a linha e que seja do tipo VARCHAR2.
      No momento só encontrei a tabela USER_TRIGGERS o campo TRIGGER_BODY, porém este campo é um LONG.
      Se não houver outro campo com essa informação VARCHAR2 como fazer para converter o LONG em VARCHAR2 no SELECT abaixo, onde preciso passar como parâmetro da função um VARCHAR2, que ela manipulará.
      No caso converter o LONG ut.trigger_body em varchar2.


      select *
      from USER_TRIGGERS ut
      WHERE
      where VERIF_ORDEM_COL_TRIGGER_AUDIT(ut.trigger_body) = 0

      Grato!

      #97641
      burga
      Participante

        Não é difícil encontrar uma TRIGGER que ultrapasse 4000 bytes de código.
        No PL/SQL o limite de tamanho pra um campo do tipo VARCHAR2 chegar a 32767 bytes mas no SQL o limite é de 4000.

        Se você quer fazer esta chamada dentro de uma instrução SQL, é difícil pois vai dar muitos problemas em relação a códigos de TRIGGERs com mais do que 4000 bytes.

        O mais garantido a refazerseu procedimento mesmo.

        Mas se ainda quiser testar, segue uma maneira de buscar o codigo de uma TRIGGER em um campo VARCHAR2, usei a cláusula MODEL pra isso:
        WITH T AS (
        SELECT LINE,
        TEXT,
        OWNER,
        NAME,
        MAX(LINE) OVER (PARTITION BY OWNER, NAME) NR_LINHA,
        LEAD(LENGTH(TEXT)) OVER (PARTITION BY OWNER, NAME ORDER BY LINE) TAM_PROX
        FROM DBA_SOURCE
        WHERE OWNER = 'OWNER_DA_TRIGGER'
        AND TYPE = 'TRIGGER'
        AND NAME = 'NOME_TRIGGER'
        ORDER BY 1 )
        SELECT TEXT2
        FROM (
        SELECT TEXT2
        FROM T
        MODEL
        PARTITION BY (T.OWNER, T.NAME)
        DIMENSION BY (T.LINE)
        MEASURES (TEXT, CAST(NULL AS VARCHAR2(4000)) AS TEXT2, 0 AS I, NR_LINHA, 0 AS I2, TAM_PROX)
        RULES ITERATE (4000000) UNTIL (I[1] >= NR_LINHA[1] OR I2[1] > 4000)
        ( TEXT2[1] = TEXT2[1] || TEXT[I[1]],
        I[1] = I[1] + 1,
        I2[1] = LENGTH(TEXT2[1])+TAM_PROX[I[1]])
        )
        WHERE TEXT2 IS NOT NULL;

        Se o código da TRIGGER ultrapassar os 4000 bytes, o codigo não retornará completo.

        Abraços,

        #97642
        gsmdf
        Participante

          Burga, realmente no SQL não dá pra fazer.
          Porém como fazer então para passar o campo LONG mesmo com o texto da trigger para minha função poder tratá-lo? Que ai na função é PLSQL e consigo atribuir o LONG a um varchar(32000) e tratá-lo.
          Há como fazer isso no select que coloquei no meu 1º post?
          Pois quando tentei passar o long fala que não pode na claúsula where…

          #97644
          leandrolbs
          Participante

            essa sua função, vai comprar o antes e o depois do script da trigger?

            se tiver scripts até 4000, tranquilo:


            CREATE TABLE trg_script (testcol CLOB);
            delete from trg_script;

            INSERT INTO trg_script
            SELECT TO_LOB(trigger_body)
            FROM user_triggers;

            select dbms_lob.substr( lt.testcol, 4000, 1 ) from trg_script lt

            Neste caso, converti para clob, e peguei os 4000 chars 1º…

            depois pode implementar algum andador pegando:

            select dbms_lob.substr( lt.testcol, 4000,8000) from trg_script lt

            mais explica a sua função, pq dependendo do capo, é possível comparar sem exibir….etc

            #97646
            gsmdf
            Participante

              Então, a função é esta:

              Programei ela antes de saber que o texto da trigger era do tipo LONG.
              Ela tem que pegar o texto da trigger, joga em duas variáveis auxiliares.Que eu supus que a simples atribuição do LONG para o varchar2(32000) funciona.
              Em ambas via expressões regulares remove-se partes da trigger e ao final compara-se essas duas variáveis auxiliares finais.
              Se forem iguais retorna 1, se forem diferentes retorna 0.

              Altero as variáveis da função pra o tipo LONG e é possível comparar LONGs entre si, cujo conteúdo são textos de triggers?
              Faço um TO_LOB para usar as funções DBMS_LOB.compare, substr,etc?
              Que aparentemente meu procedimento não tá gerando valores corretos para as variáveis, pois a comparação ao final tá dando diferente do esperado.


              /* Formatted on 10/1/2011 11:32:35 (QP5 v5.115.810.9015) /
              CREATE OR REPLACE FUNCTION TCU.VERIF_ORDEM_COL_TRIGGER_AUDIT (
              TEXTO_TRIGGER LONG
              )
              RETURN SMALLINT
              AS
              /
              Retorna true se está consistente ou false se está inconsistente*/

              --
              primeiroBloco VARCHAR2(32000);
              segundoBloco VARCHAR2(32000); --SYS.DBA_SOURCE.TEXT%TYPE;

              BEGIN
              primeiroBloco := TEXTO_TRIGGER; /Variaveis V_ e N_/
              segundoBloco := TEXTO_TRIGGER; /Variaveis :OLD. e :NEW./
              /Separando as colunas do primeiro Bloco./
              primeiroBloco :=
              REGEXP_REPLACE (
              primeiroBloco,
              'DROP([[:print:]|[:cntrl:]])INSERT INTO([[:print:]])([ |[:cntrl:]])('
              );
              primeiroBloco :=
              REGEXP_REPLACE (primeiroBloco,
              ', OPERACAO_EFETUADA([[:print:]|[:cntrl:]])
              ');
              primeiroBloco := REGEXP_REPLACE (primeiroBloco, 'V_');
              primeiroBloco := REGEXP_REPLACE (primeiroBloco, 'N_');

              /Primeiro Bloco agora só com os nomes das variaveis,em ordem, sem prefixo, separados por virgula/

              /Separando as colunas do segundo Bloco./
              segundoBloco :=
              REGEXP_REPLACE (
              segundoBloco,
              'DROP([[:print:]|[:cntrl:]])VALUES([[:print:]|[:cntrl:]])('
              );
              segundoBloco :=
              REGEXP_REPLACE (segundoBloco, ', V_ChangeType([[:print:]|[:cntrl:]])*');
              segundoBloco := REGEXP_REPLACE (segundoBloco, ':OLD.');
              segundoBloco := REGEXP_REPLACE (segundoBloco, ':NEW.');

              /Segundo Bloco agora só com nome das variaveis, em ordem, sem prefixo, separadas por virgula./

              IF primeiroBloco = segundoBloco
              THEN
              RETURN 1;
              ELSE
              RETURN 0;
              END IF;

              END;
              /

              #97650
              Ishii
              Participante

                Olá,

                Mais uma vez, oremos para o Mestre Kyte…

                http://bit.ly/gM0iE9

                []s Ishii

              Visualizando 6 posts - 1 até 6 (de 6 do total)
              • Você deve fazer login para responder a este tópico.