Re: [oracle_br] Diferença executando REGEXP_LIKE
Sim, ** um ou dois checks ** de regras dentro de strings Sem Dúvida são enxutos usando expressões regulares, mas RAPIDAMENTE ao vc acumular várias regras (e são MESMO VÁRIAS, essa meia dúzia de regras que citei são apenas ALGUMAS das mais importantes, nãoe esgotam Não as possibilidades!) vc vai ver que a coisa começa a ficar Complexa pra debugar - EM ESPECIAL porque, ao invés de termos comandos, tudo fica em caracteres funcionais numa expressão só - eu fico perdidinho Fácil a hora que a expressão regular começa a ter mais de uma dúzia de caracteres funcionais, fácil Por exemplo, digamos que vamos implementar a regra de que o email tem que começar por letra , o caracter para indicar começo da string é ^, para assegurar que a string contenha elementos de uma lista é [] , e para representar letraz de A a Z usamos A-Z, então fica assim : ^[A-Z] mas ainda tem mais o que colocar a regra de obrigatório um @ (isso é o sinal de +), que depois do @ tem que vir alfanumérico, chegamos nisto : ^[A-Z]+@[A-Z0-9] e aí vai, vc vai ver que fácil pra chegar numa expressão regular usável, implementando pelo menos essa meia dúzia simples de regras, muito provavelmente vamos chegar numa dúzia opu mais de comandos regulares, pra mim isso não é algo Enxuto pra se debugar/entender/analisar - pode ser Enxuto no sentido de menos texto escrito, menos código, mas pra se ENTENDER a lógica (permitindo posterior debug) nem sempre... Senso assim, a minha Preferência pessoal seria mesmo por fazer algo mais ou menos como exemplificado, separando os IFs, mas vai da preferência, mesmo : afinal, se é verdade que normalmente é mais fácil de se entender/analisar código linear E código explícito não tem o consumo de CPU por vezes louco das regexps, como eu tinha dito antes SE consumo extra não é uma preocupação E SE a pessoa tá acostumada com regexps, COM CERTEZA usando regexp vai escrever SIm um código mais curto : http://www.regular-expressions.info/email.html é om ponto de partida interessante pra esses casos... []s Chiappa OBS : é importante, creio, que se frise (pela última vez na thread, mais pra consumo de eventuais leitores que não acompanharam do começo) que comparações com strings (pra ver se há caracteres alfabéticos dentro dela, por exemplo) são TOTALMENTE DEPENDENTES das questões NLS para que o RDBMS possa 'entender' que as letras acentuadas Fazem Parte do conjunto de caracteres alfabéticos, o link que indiquei acima Re-afirma esse importante ponto Assim sendo, como eu havia dito repito :o CERTO, o Recomendado, o modo Ótimo de se trabalhar é se ASSEGURAR que o setting de NLS da sessão-cliente é O MESMO (ou pelo menos COmpatível) com os settings NLS do banco, aí tanto expressões regexp como A-Z funcionam, Quanto também é Possível incluir no código de verificação de email sendo escrito linhas para convertemos as letras acentuadas para letras comuns Ou então usarmos as funções que tratam strings localizadas.
Re: [oracle_br] Diferença executando REGEXP_LIKE
Zilmar, boa noite! Talvez o código abaixo ajude. Com expressão regular, fica bem mais enxuto. Mas creio que isso aí possa te ajudar. Fonte: https://community.oracle.com/thread/666479 Tenho uma função de validação de email na empresa em que trabalho. É algo bem similar a este código abaixo. Amanhã eu posto aqui. Abraços! ***PL/SQL code for Email validation*** DECLARE t_valid NUMBER(1); t_totallen NUMBER(2); t_counter NUMBER(2):=0; t_atpos NUMBER(2):= 1; i NUMBER(2) := 1; t_pointpos NUMBER(2):= 1; mail_ch VARCHAR2(1); result number; --:GR BEGIN t_totallen := LENGTH(:text_item_email); t_counter := t_totallen; i := 1; t_valid := 1; - IF LENGTH(ltrim(rtrim(:text_item_email))) = 0 THEN t_valid := 0; ELSE --- --This is to check special characters are present or not in the email ID t_counter := t_totallen; WHILE t_counter > 0 LOOP mail_ch := substr(:text_item_email,i,1); i := i+1; t_counter := t_counter -1; IF mail_ch IN (' ','!','#','$','%','^','&','*','(',')','-','','"', '+','|','{','}','[',']',':','>','<','?','/','\','=') THEN t_valid := 0; EXIT; END IF; END LOOP; --- --This is to check more than one '@' character present or not t_atpos := instr(:text_item_email,'@',1,2) ; IF t_atpos > 1 then t_valid := 0; END IF; --- --This is to check at minimum and at maximum only one '@' character present t_atpos := instr(:text_item_email,'@',1) ; IF t_atpos IN (0,1) THEN t_valid := 0; END IF; --- --This is to check at least one '.' character present or not t_pointpos := instr(:text_item_email,'.',1) ; IF t_pointpos IN (0,1) THEN t_valid := 0; END IF; --- --This is to check at least one character is present between @ and '.' :GR t_atpos := instr(:text_item_email,'@',1) ; t_pointpos := instr(:text_item_email,'.',1) ; IF t_pointpos-t_atpos<=1 THEN t_valid := 0; END IF; --- --This is to check at least one character is present after '.' :GR t_pointpos := instr(:text_item_email,'.',1) ; IF t_totallen-t_pointpos<=0 THEN t_valid := 0; END IF; --- END IF; if(t_valid=0) then message('Invalid Email'); result:=show_alert('alert_email'); raise form_trigger_failure; end if; END; ---***PL/SQL code for Name Validation***--- DECLARE t_valid NUMBER(1); t_totallen NUMBER(2); t_counter NUMBER(2):=0; i NUMBER(2) := 1; name_ch VARCHAR2(1); --name_ch_ascii NUMBER; result number; --:GR BEGIN t_totallen := LENGTH(:text_item_first_name); t_counter := t_totallen; i := 1; t_valid := 1; - IF LENGTH(ltrim(rtrim(:text_item_first_name))) = 0 THEN t_valid := 0; ELSE --- --This is to check if each character in name lies in the valid ascii range t_counter := t_totallen; WHILE t_counter > 0 LOOP name_ch := upper(substr(:text_item_first_name,i,1)); --name_ch_ascii := convert(name_ch,'US7ASCII'); i := i+1; t_counter := t_counter -1; --IF name_ch_ascii not between 65 and 90 THEN IF name_ch not between 'A' and 'Z' THEN t_valid := 0; EXIT; END IF; END LOOP; --- END IF; if(t_valid=0) then message('Invalid First Name'); result:=show_alert('alert_first_name'); raise form_trigger_failure; end if; END; Em 4 de outubro de 2016 21:28, zfurq...@gmail.com [oracle_br] < oracle_br@yahoogrupos.com.br> escreveu: > > > Chiappa, > > Entendo e concordo com os pontos que você colocou, mas na verdade, o que > queremos é simplesmente uma função de validação de endereços de email. > > Colegas, alguém tem uma função para isso, preferencialmente que não > utilize o REGEXP_LIKE ? > > Grato a todos pela ajuda. > > Zilmar Furquim > Synchro Systems > > > -- Atenciosamente, *Gustavo Guedes de Sene*
Re: [oracle_br] Diferença executando REGEXP_LIKE
Bem, pondo de parte de momento as considerações *** todas *** que eu coloquei sobre NLS (e que vc TEM que conhecer e TEM que levar em conta em Qualquer Desenvolvimento), mas enfim : não tenho uma Rotina pronta mas afaik quando se fala em validação de email as checagens que podemos fazer (afora tentar ** enviar ** um email para a conta especificada :) Não São tão complexas assim, imho é muito mais Trabnalhoso do que complexo... Elas seriam + ou - : => caracter @ presente, e com UMA só ocorrência => endereço de email começa com caracter alfabético => não pode haver espaços em branco em nenhuma Posição => não são aceitos outros caracteres afora alfanuméricos, arroba, underline, sinal de subtração e pontos => a porção da string após o @ (ie, o Domínio) ** tem ** que ter ao menos um caracter alfanúmerico após o @ => após o @ Tem que haver uma sequência .xxx (que se vc quiser pode validar numa lista composta por .com , .net, .mus, .org e alguns outros possíveis - googla que vc acha listas mais completas) E opcionalmente após essa sequência pode haver outra sequência .xx para identificar o País - novamente, googla que vc acha a lista de Países possíveis E para evitar minúsculas/maiúsculas converter tudo para maiúsculas ou minúsculas, via UPPER/LOWER/NLS_UPPER ou o que for... Tudo isso imho é plenamente possível de se implementar com as built-ins primiticas de string, não vejo necessidade Obrigatória de usar REGULAR EXPRESSIONS Por exemplo, contar ocorrências de caracter @ poderia ser (supondo que V_EMAIL é uma variável string que contém a conta de email a validar) : LENGTH(V_EMAIL) - LENGTH( REPLACE (V_EMAIL, '@') Buscar a posição onde ocorreu um dado caracter é com INSTR, e por aí vai REPITO, não é rocket science imho mas VAI dar trabalho, vc vai ter que meter vários IFs na sua rotina PL/SQL creio... Obviamente, se vc está mais acostumado com expressões regulares do que com as built-ins originais de strings E o consumo maior de CPU (e a maior cpomplexidade de regexp, imho) não te incomodam, vc pode Tranquilamente usar REGEXP... ==> O MAIS IMPORTANTE aqui, porém, é que como eu disse se houver a mínima chance de vc ter uma sessão não configurada corretamente no que se refere a NLS, vc TEM QUE PREVENIR ISSO, okdoc ? As suas opções são as que expus, ie : converter (para UNICODE, talvez) com convert , OU trocar as letras acentuadas por suas equivalentes sem acento via TRANSLATE, OU via ALTER SESSION setar o NLS correto, OU usar as versões Unicode das funcões de string (como INSTRC) ou de regexp... Blz ?? Isso vc TEM QUE SE PREOCUPAR de qualquer forma (seja usando built-ins primitivas seja usando regexp) se há a menor chance de NLS settings diversos e/ou se vc não tem controle sobre os NLS settings da sessão e/ou do banco... []s Chiappa
Re: [oracle_br] Diferença executando REGEXP_LIKE
Chiappa, Entendo e concordo com os pontos que você colocou, mas na verdade, o que queremos é simplesmente uma função de validação de endereços de email. Colegas, alguém tem uma função para isso, preferencialmente que não utilize o REGEXP_LIKE ? Grato a todos pela ajuda. Zilmar Furquim Synchro Systems
Re: [oracle_br] Diferença executando REGEXP_LIKE
Opa, blz ? Eu uso ** o menos Possível ** expressões regulares no RDBMS Oracle (principalmente por causa da maior complexidade delas E pelo fato de elas consumirem muito mais CPU do que as funções de string primitivas), mas não vou entrar no mérito, vou falar sobre Localização, que parece ser a sua dúvida princiapl... Antes de mais nada, para podermos discutir Localização please goto manual "Database Globalization Support Guide" - lá vc vai achar Documentado que : a) os parâmetros de Localização (ie, Linguagem, Characterset, território, etc) definidos a nível de database para o input são considerados DEFAULTs, ie, entram em ação SE e APENAS SE a sessão-cliente NÂO especificar nenhum deles - em a sessão especificando algum deles, NECESSARIAMENTE o setting da sessão VAI SOBREPOR o do database, afaik inespacavelmente b) lembre que quando o RDBMS vai ** gravar ** no database uma string, aí sim ele vai usar os settings de locale (EM ESPECIAL o characterset) do database , sendo que se o characterset da sessão for diferente do characterset parametrizado no database o RDBMS vai tentar CONVERTER a string para o characterset do database - caso o characterset do database seja um superset , seja ** SUPERIOR ** ao do cliente (ie, o characterset do db contém todos os caracteres usados/representados no characterset da sessão) não vai haver perda nenhuma mas se não for vc PODE SIM ter perdas de dados e/ou caracteres convertidos inadequadamente... Sendo assim, é por isso que se vc tem dois databases usados no mesmo ambiente mas com charactersets/locales diferentes, vc PODE ter uma bomba-relógio aí esperando pra te pegar... Não é seu caso, ao que entendo vc não está gravando nada, mas Fique esperto, já que estamos discutindo NLS... c) vc até pode Automatizar a alteração de local de uma sessão (por exemplo, tendo um ALTER SESSION sendo disparado automaticamente quando a sessão conecta no database, via trigger de logon, digamos) mas que FIQUE CLARO que isso é uma Gambi - o CERTO, o CORRETO, o INDICADO é que Realmente vc CONFIGURE ADEQUADAMENTE na aplicação os dados de local (NLS, para usar o jargão Oracle) - normalmente isso se faz setando variáveis de ambiente como NLS_LANG e similares, veja lá Esses conceitos claros, aí as suas respostas seguem : 1. não, cfrme a) acima os settings da sessão Sobrepõem os do database para processamento de input 2. sim, se vc quiser ter um ALTER SESSION na sua rotina PL/SQL se usa um EXECUTE IMMEDIATE - http://www.orafaq.com/forum/t/16528/ exemplifica Além disso, alguns pontos que vc tem que ter em mente e que te podem ser úteis, também : p1 : o RDBMS Oracle possui funções nativas para converter uma string para um dado characterset (função CONVERT) e Também para remover/trocar por outros determinados caracteres - por exemplo, se vc quisesse trocar as letras acentuadas por seus equivalentes sem acentos, vc pode fazer um TRANSLATE(string, 'áéíóú', 'aeiou') ou coisas assim : goto manual "Oracle SQL Language Reference" para refs sobre CONVERT, TRANSLATE, REPLACE, etc p2 : embora eu não use muito, vi na Documentação (mesmo manual "SQL Reference" acima indicado) que a REGEXP_LIKE possui além da condição LIKE as condições LIKE2, LIKE4 e LIKEC que trabalham com characterset universal (UNICODE) - pode ser uma opção para que vc tenha a string sempre tratada da mesma maneira, no caso sempre convertida pra UNICODE, independente do que temos no database p3 : se te ajudar, o mesmo manual "SQL Reference" nos diz também que vc pode ter processamento CASE-INSENSITIVE e/ou Insensível a acentuação setando NLS_SORT e NLS_COMP na sessão, veja se isso te ajuda []s Chiappa
Re: [oracle_br] Diferença executando REGEXP_LIKE
Muito obrigado Emerson, me ajudou muito com os links. Acredito que achei o motivo do problema e estou pesquisando soluções, inclusive pedindo ajuda no grupo. Abs, Zilmar Furquim Synchro Systems
Re: [oracle_br] Diferença executando REGEXP_LIKE
Colegas, Acho que descobri o que deve ser o motivo do problema: NLS_LANGUAGE diferentes nas sessions Vejam abaixo: SQL> SELECT * FROM V$NLS_PARAMETERS; PARAMETERVALUE NLS_LANGUAGE BRAZILIAN PORTUGUESE NLS_TERRITORYBRAZIL NLS_CURRENCY R$ NLS_ISO_CURRENCY BRAZIL NLS_NUMERIC_CHARACTERS ., NLS_CALENDAR GREGORIAN NLS_DATE_FORMAT DD-MON-RR NLS_DATE_LANGUAGEBRAZILIAN PORTUGUESE NLS_CHARACTERSET WE8ISO8859P1 NLS_SORT WEST_EUROPEAN NLS_TIME_FORMAT HH24:MI:SSXFF NLS_TIMESTAMP_FORMAT DD/MM/RR HH24:MI:SSXFF NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR NLS_TIMESTAMP_TZ_FORMAT DD/MM/RR HH24:MI:SSXFF TZR NLS_DUAL_CURRENCYCr$ NLS_NCHAR_CHARACTERSET AL16UTF16 NLS_COMP BINARY NLS_LENGTH_SEMANTICS BYTE NLS_NCHAR_CONV_EXCP FALSE 19 linhas selecionadas. SQL> ALTER SESSION SET NLS_LANGUAGE = 'BRAZILIAN PORTUGUESE'; Sessão alterada. SQL> Declare 2 nResultNumber; 3 Begin 4 Begin 5 Select 1 6 Into nResult 7 From dual 8 Where REGEXP_LIKE ( 'lilian.leite@autoação2000.com.br','^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$'); 9 Exception 10 When Others Then 11 nResult := 0; 12 End; 13 Dbms_Output.Put_Line('nResult='||nResult); 14 End; 15 / nResult=1 Procedimento PL/SQL concluído com sucesso. SQL> ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN'; Session altered. SQL> Declare 2 nResultNumber; 3 Begin 4 Begin 5 Select 1 6 Into nResult 7 From dual 8 Where REGEXP_LIKE ( 'lilian.leite@autoação2000.com.br','^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$'); 9 Exception 10 When Others Then 11 nResult := 0; 12 End; 13 Dbms_Output.Put_Line('nResult='||nResult); 14 End; 15 / nResult=0 PL/SQL procedure successfully completed. Conclusão: Com o NLS_LANGUAGE = 'AMERICAN', os caracteres acentuados não são considerados no meu REGEXP_LIKE, que é o resultado que desejo. Já com o NLS_LANGUAGE = 'BRAZILIAN PORTUGUESE', os caracteres acentuados são considerados no REGEXP_LIKE e trazem um resultado indesejado. Pergunta: O bloco acima foi utilizado somente para demonstrar o problema. Na verdade, esse código está numa função compilada no banco. Existe alguma forma de fazer com que esse parâmetro seja desprezado, sendo considerado sempre a nível de banco e não de session ? Uma possibilidade seria incluir o "execute_immediate" abaixo na function. Já teste e funciona, mas gostaria de evitar fazer dessa forma se fosse possível: EXECUTE IMMEDIATE('ALTER SESSION SET NLS_LANGUAGE = "AMERICAN"'); É possível inclusive preservar o NLS_LANGUAGE original buscando-o na V$NLS_PARAMETERS e no final da function voltar a deixar como estava executando outro "EXECUTE IMMEDIATE" Aguardo sugestões e comentários dos colegas. Abs, Zilmar Furquim Synchro Systems
RE: [oracle_br] Diferença executando REGEXP_LIKE
Tu já sabe que o comportamento é diferente devido a configuração da sessão, qual é exatamente a tua dúvida? Étore From: oracle_br@yahoogrupos.com.br [mailto:oracle_br@yahoogrupos.com.br] Sent: terça-feira, 4 de outubro de 2016 18:38 To: oracle_br@yahoogrupos.com.br Subject: Re: [oracle_br] Diferença executando REGEXP_LIKE Emerson, Obrigado pelo retorno, mas no link que você passou não consegui achar nada que me ajudasse a resolver o problema. Se mais alguém puder ajudar ficarei muito agradecido. Abs, Zilmar Furquim Synchro Systems [As partes desta mensagem que não continham texto foram removidas]
Re: [oracle_br] Diferença executando REGEXP_LIKE
Zilmar, Acredito que seja alguma configuração do cliente configurado na sua maquina, que esteja mudando o comportamento do resultado, os parâmetros que interferem nisso é o NLS_LANG, segue abaixo algumas referências para verificar isso: https://docs.oracle.com/html/B13804_02/gblsupp.htm http://www.cooperati.com.br/2013/05/08/oracle-parmetros-de-sesso-alterando-nls-da-conexo/ http://eduardolegatti.blogspot.com.br/2013/04/ignorando-caracteres-acentuados.html http://aserlorenzo.com/manSQL/Oracle/dml/funcoes/formatdatasnumeros.htm http://www.leniel.net/2010/03/oracle-nlslang-character-set-encoding.html#sthash.g6E6qqie.dpbs Att, Emerson Em 4 de outubro de 2016 17:21, zfurq...@gmail.com [oracle_br] < oracle_br@yahoogrupos.com.br> escreveu: > > > Colegas, > > Complementando minha dúvida, o problema ocorre devido aos caracteres > acentuados, que numa máquina são considerados e geram o erro (o que seria o > esperado) e em outra máquina não são considerados e portanto não geram erro > e trazem um resultado incorreto a princípio. > > Ajudem-me por favor, mestres do Oracle (Chiappa e cia). > > > Abs, > Zilmar Furquim > > >
Re: [oracle_br] Diferença executando REGEXP_LIKE
Zilmar, Desculpe pela correria, li muito por cima e acabei não entendendo corretamente sua necessidade. Repassei algumas referência no e-mail anterior que podem te auxiliar para entender o que está acontecendo nesta sua situação. Att, Emerson Em 4 de outubro de 2016 17:38, zfurq...@gmail.com [oracle_br] < oracle_br@yahoogrupos.com.br> escreveu: > > > Emerson, > > Obrigado pelo retorno, mas no link que você passou não consegui achar nada > que me ajudasse a resolver o problema. > > Se mais alguém puder ajudar ficarei muito agradecido. > > Abs, > Zilmar Furquim > Synchro Systems > > >
Re: [oracle_br] Diferença executando REGEXP_LIKE
Emerson, Obrigado pelo retorno, mas no link que você passou não consegui achar nada que me ajudasse a resolver o problema. Se mais alguém puder ajudar ficarei muito agradecido. Abs, Zilmar Furquim Synchro Systems
Re: [oracle_br] Diferença executando REGEXP_LIKE
Colegas, Complementando minha dúvida, o problema ocorre devido aos caracteres acentuados, que numa máquina são considerados e geram o erro (o que seria o esperado) e em outra máquina não são considerados e portanto não geram erro e trazem um resultado incorreto a princípio. Ajudem-me por favor, mestres do Oracle (Chiappa e cia). Abs, Zilmar Furquim
Re: [oracle_br] Diferença executando REGEXP_LIKE
Boa tarde Zilmar, Segue abaixo, link com algumas implentações utilizando regex no Oracle: http://blog.gaudencio.net.br/2016/10/oracle-utilizando-regex-para-consultas.html Att, Emerson Em 4 de outubro de 2016 16:56, zfurq...@gmail.com [oracle_br] < oracle_br@yahoogrupos.com.br> escreveu: > > > Boa tarde colegas, > > > Alguém sabe me dizer se existe algum setting de sessão e/ou de banco ou > qualquer outra coisa que possa alterar o resultado de um REGEXP_LIKE ??? > > > Rodando o exemplo abaixo no SQL*Plus, para mim sempre retorna 1, mas para > um outro colega em um outro local retorna sempre 0 (zero). > > A intenção é que o resultado fosse ZERO mesmo (indicando um erro), mas > estamos tendo problema porque volta 0 conforme abaixo: > > > SQL*Plus: Release 10.2.0.1.0 - Production on Ter Out 4 17:54:55 2016 > > > Copyright (c) 1982, 2005, Oracle. All rights reserved. > > > > Conectado a: > > Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit > Production > > With the Partitioning, Oracle Label Security, OLAP, Data Mining Scoring > Engine > > and Real Application Testing options > > > SVP> Declare > > 2 nResultNumber; > > 3 Begin > > 4 Begin > > 5 Select 1 > > 6 Into nResult > > 7 From dual > > 8 Where REGEXP_LIKE ( 'lilian.leite@autoação2000.com.br > ','^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$'); > > 9 Exception > > 10 When Others Then > > 11 nResult := 0; > > 12 End; > > 13 Dbms_Output.Put_Line('nResult='||nResult); > > 14 End; > > 15 / > > nResult=1 > > > Procedimento PL/SQL concluído com sucesso. > > > Alguma luz ??? > > > Obrigado, > > > Zilmar Furquim > > Synchro Systems > > > > >