- Este tópico contém 5 respostas, 4 vozes e foi atualizado pela última vez 15 anos, 2 meses atrás por
Ishii.
-
AutorPosts
-
11 de janeiro de 2011 às 9:31 pm #97636
gsmdf
ParticipanteOlá,
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!
11 de janeiro de 2011 às 10:38 pm #97641burga
ParticipanteNã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,
11 de janeiro de 2011 às 10:49 pm #97642gsmdf
ParticipanteBurga, 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…11 de janeiro de 2011 às 11:10 pm #97644leandrolbs
Participanteessa 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
11 de janeiro de 2011 às 11:30 pm #97646gsmdf
ParticipanteEntã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;
/12 de janeiro de 2011 às 4:26 am #97650Ishii
Participante -
AutorPosts
- Você deve fazer login para responder a este tópico.