Pergunta

Olá, estou tentando armazenar nomes em um banco de dados Oracle e recuperá-los usando PHP e oci8.

No entanto, se eu inserir o é diretamente no banco de dados Oracle e uso oci8 para recuperá-lo, acabei de receber um e

Devo codificar todos os caracteres especiais (incluindo é) em entidades HTML (ou seja: é) antes de inserir no banco de dados ...Ou eu estou esquecendo de alguma coisa ?

THX


ATUALIZAR:1º de março às 18h40

encontrei esta função:http://www.php.net/manual/en/function.utf8-decode.php#85034

function charset_decode_utf_8($string) {
    if(@!ereg("[\200-\237]",$string) && @!ereg("[\241-\377]",$string)) {
        return $string;
    }
$string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e","'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'",$string);
$string = preg_replace("/([\300-\337])([\200-\277])/e","'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",$string);
return $string;
}

parece funcionar, embora não tenha certeza se é a solução ideal


ATUALIZAR:8 de março às 15h45

O conjunto de caracteres da Oracle é ISO-8859-1.
em PHP eu adicionei:

putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1");

para forçar a conexão oci8 a usar esse conjunto de caracteres.Recuperando o é usar oci8 do PHP agora funcionou!(para varchars, mas não CLOBs tive que fazer utf8_encode para extraí-lo)
Então tentei salvar os dados do PHP no Oracle...e não funciona..em algum lugar ao longo do caminho do PHP ao Oracle, o é se torna um ?


ATUALIZAR:9 de março às 14h47

Então, chegando mais perto.Depois de adicionar a variável NLS_LANG, fazendo inserções diretas de oci8 com é funciona.

O problema está realmente no lado do PHP.Ao usar o framework ExtJs, ao enviar um formulário ele o codifica usando encodeURIComponent.
Então é é enviado como %C3%A9 e então recodificado em é.
No entanto, seu comprimento é agora 2 (strlen($my_sent_value) = 2) e não 1.E se em PHP eu tentar:$meu_valor_enviado == é = FALSO

Acho que se eu conseguir recodificar todos esses caracteres em PHP de volta em comprimentos de byte 1 e depois inseri-los no Oracle, isso deve funcionar.

Ainda sem sorte


ATUALIZAR:10 de março às 11h05

Continuo pensando que estou tão perto (mas tão longe).

putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9"); funciona muito esporadicamente.

Criei um pequeno script php para testar:

header('Content-Type: text/plain; charset=ISO-8859-1');
putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9");
$conn= oci_connect("user", "pass", "DB");
$stmt = oci_parse($conn, "UPDATE temp_tb SET string_field = '|é|'");
oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);

Depois de executar isso uma vez e fazer login diretamente no banco de dados Oracle, vejo que STRING_FIELD está definido como |¿|.Obviamente não é o que eu esperava da minha experiência anterior.
No entanto, se eu atualizar essa página PHP duas vezes rapidamente....funcionou !!!
No Oracle eu vi corretamente |é|.

Parece que talvez a variável de ambiente não esteja sendo configurada corretamente ou enviada a tempo para a primeira execução do script, mas está disponível para a segunda execução.

Meu próximo experimento é exportar a variável para o ambiente do PHP, porém, preciso redefinir o Apache para isso... então veremos o que acontece, espero que funcione.

Foi útil?

Solução 2

Foi isso que finalmente acabei fazendo para resolver esse problema:

Modificou o perfil do Daemon em execução PHP para ter:

NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1

Para que a conexão OCI8 use ISO-8859-1.

Então, na minha configuração PHP, defina o tipo de conteúdo padrão como ISO-8859-1:

default_charset = "iso-8859-1"

Quando estou inserindo uma tabela de oráculos via OCI8 do PHP, eu faço:

utf8_decode($my_sent_value)

E ao receber dados do Oracle, a impressão da variável deve funcionar assim:

echo $my_received_value

No entanto, ao enviar esses dados sobre o Ajax, tive que usar:

utf8_encode($my_received_value)

Outras dicas

Presumo que você esteja ciente destes fatos:

  • Existem muitos conjuntos de caracteres diferentes:você tem que escolher um e, claro, saber qual está usando.
  • Oracle é perfeitamente capaz de armazenar texto sem entidades HTML (é).Entidades HTML são usadas em HTML.Oracle não é um navegador web ;-)

Você também deve saber que as entidades HTML não estão vinculadas a um conjunto de caracteres específico;pelo contrário, eles são usados ​​para representar caracteres em um contexto independente do conjunto de caracteres.

Você fala indistintamente sobre ISO-8859-1 e UTF-8.Qual conjunto de caracteres você deseja usar?ISO-8859-1 é fácil de usar, mas só pode armazenar texto em alguns idiomas latinos (como espanhol) e não possui alguns caracteres comuns, como o símbolo €.UTF-8 é mais complicado de usar, mas pode armazenar todos os caracteres definidos pelo consórcio Unicode (que inclui tudo que você precisa).

Depois de tomar a decisão, você deve configurar o Oracle para armazenar dados nesse conjunto de caracteres e escolher um tipo de coluna apropriado.Por exemplo, VARCHAR2 é adequado para ASCII simples, NVARCHAR2 é adequado para UTF-8.

Se você realmente não pode alterar o conjunto de caracteres que o Oracle usará, e a codificação base64 que codifica seus dados antes de armazená -los no banco de dados. Dessa forma, você pode aceitar caracteres de qualquer conjunto de caracteres e armazená-los como ISO-8859-1 (porque a base64 produzirá um subconjunto do conjunto de caracteres ASCII que mapeia exatamente para ISO-8859-1). A codificação base64 aumentará o comprimento da corda em, em média, 37%

Se seus dados só serão exibidos como HTML, você também poderá armazenar entidades HTML como sugeriu, mas esteja ciente de que uma única entidade pode ter até 10 caracteres por personagem não codificado, por exemplo, é ϑ

Eu tive que enfrentar esse problema: os personagens especiais latinamericanos são armazenados como "?" ou "" "No meu banco de dados Oracle ... Não posso alterar o NLS_Character_Set porque não somos os proprietários do banco de dados.

Então, eu encontrei uma solução alternativa:

1) Código ASP.NET Crie uma função que converte String em caracteres hexadecimais:

    public string ConvertirStringAHex(String input)
    {
        Encoding encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
        Byte[] stringBytes = encoding.GetBytes(input);
        StringBuilder sbBytes = new StringBuilder(stringBytes.Length);
        foreach (byte b in stringBytes)
        {
            sbBytes.AppendFormat("{0:X2}", b);
        }
        return sbBytes.ToString();
    }

2) Aplique a função acima à variável que você deseja codificar, assim

     myVariableHex = ConvertirStringZHex( myVariable );

No Oracle, use o seguinte:

 PROCEDURE STORE_IN_TABLE( iTEXTO IN VARCHAR2 )
 IS
 BEGIN
   INSERT INTO myTable( SPECIAL_TEXT )  
   VALUES ( UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW( iTEXTO ));
   COMMIT;
 END;

Obviamente, o ITEXTO é o parâmetro Oracle que recebe o valor de "MyVariableHex" do código ASP.NET.

Espero que ajude ... se houver algo para melhorar, por favor, não hesite em postar seus comentários.

Fontes:http://www.nullskull.com/faq/834/convert-string-to-hex-and-hex-to-tring-in-net.aspx https://forums.oracle.com/thread/44799

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top