2010-03-01 2 views
4

Привет Я пытаюсь хранить имена в базе данных Oracle и извлекать их с помощью PHP и oci8.Работа с eacute и другими специальными символами с использованием Oracle, PHP и Oci8

Однако, если я вставляю é непосредственно в базу данных Oracle и использовать oci8, чтобы принести его назад, я просто получите e

ли я кодировать все специальные символы (включая é) в HTML лиц (то есть: é) перед вставкой в ​​базу данных ... или я чего-то не хватает?

Thx


UPDATE: Мар 1 в 18:40

нашел эту функцию: 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; 
} 

, кажется, работает, хотя и не уверен, что если его оптимальное решение


UPDATE: 8 мар в 15:45

набора символов Oracle является ISO-8859-1.
в PHP Я добавил:

putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1"); 

, чтобы заставить соединение oci8 использовать этот набор символов. Получение é с использованием oci8 с PHP теперь сработало! (Для varchars, но не CLOBs должен был сделать utf8_encode, чтобы извлечь его)
Затем я попытался сохранить данные из PHP в Oracle ... и оно не work..somewhere по пути из PHP в оракул é становится ?


UPDATE: 9 мар в 14:47

Так ближе. После добавления переменной NLS_LANG выполняются прямые вставки oci8 с é.

Проблема на самом деле на стороне PHP. Используя структуру ExtJs, при отправке формы она кодирует ее с использованием encodeURIComponent.
Так é отправлено как %C3%A9, а затем перекодировано в é.
Однако его длина теперь (strlen($my_sent_value) = 2) и не 1. И если в PHP я пытаюсь: $ my_sent_value == é = FALSE

Я думаю, если я могу перекодировать все эти символы в PHP возвращается в длину байта размером 1, а затем вставляя их в Oracle, он должен работать.

Еще не повезло, хотя


UPDATE: 10 мар в 11:05

Я продолжаю думать, что я так близко (но так далеко).

putenv("NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P9"); работает очень спорадически.

Я создал небольшой скрипт для проверки:

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); 

После запуска один раз и Логгина в базу данных Oracle непосредственно я вижу, что STRING_FIELD установлен в |¿|. Очевидно, не то, что я ожидал от своего предыдущего опыта.
Однако, если я обновляю эту страницу PHP дважды быстро ... это сработало !!!
В Oracle я правильно увидел |é|.

Похоже, что переменная окружения не была правильно установлена ​​или отправлена ​​во время первого выполнения скрипта, но доступна для второго выполнения.

Мой следующий эксперимент заключается в том, чтобы экспортировать переменную в среду PHP, однако мне нужно сбросить Apache для этого ... поэтому мы посмотрим, что произойдет, надеюсь, это сработает.

+1

Какой набор символов является база данных в? Вы можете использовать 'select property_value from database_properties, где property_name = 'NLS_CHARACTERSET'; чтобы узнать. ' –

+0

вы можете ответить на свой вопрос;) –

+0

Я бы подождал, отвечая на вопрос самостоятельно, все еще могут быть лучшие способы сделать это ... –

ответ

1

Это то, что я, наконец, в конечном итоге делает, чтобы решить эту проблему:

Измененный профиль демона под управлением PHP, чтобы иметь:

NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1 

Так что соединение oci8 использует ISO-8859 -1.

Тогда в моей конфигурации PHP установить тип содержимого по умолчанию ISO-8859-1:

default_charset = "iso-8859-1" 

Когда я вставив в Oracle таблицы с помощью OCI8 из PHP, я делаю:

utf8_decode($my_sent_value) 

И при получении данных от Oracle, печать переменной должна просто работать так:

echo $my_received_value 

Однако ж курица отправки этих данных через AJAX я должен был использовать:

utf8_encode($my_received_value) 
2

Я полагаю, вы знаете об этих фактах:

  • Есть много различных наборов символов: вы должны выбрать один и, конечно же, знают, какой из них вы используете.
  • Oracle отлично умеет хранить текст без объектов HTML (é). HTML-объекты используются, ну, HTML. Oracle не является веб-браузером ;-)

Вы также должны знать, что объекты HTML не привязаны к определенной кодировке; напротив, они используются для представления символов в контексте, не зависящем от набора символов.

Вы нечетко говорите об ISO-8859-1 и UTF-8. Какую кодировку вы хотите использовать? ISO-8859-1 прост в использовании, но он может хранить только текст на некоторых латинских языках (например, на испанском языке), и ему не хватает общих символов, таких как символ. UTF-8 сложнее использовать, но он может хранить все символы, определенные консорциумом Unicode (включая все, что вам когда-либо понадобится).

После того, как вы приняли решение, вы должны настроить Oracle для хранения данных в такой кодировке и выбрать подходящий тип столбца. Например, VARCHAR2 отлично подходит для простого ASCII, NVARCHAR2 подходит для UTF-8.

+0

Thx для ответа. База данных Oracle, которую я использую, использует ISO-8859-1, я не могу ее изменить. Я предполагаю, что это означает, что мой PHP тоже должен использовать его ... но после ручного хранения é в базе данных и использования oci8 для его получения я получаю только e (not é) – ddallala

0

Если вы действительно не можете изменить набор символов, который будет использовать оракул, то как насчет Base64, кодирующего ваши данные, прежде чем хранить его в базе данных. Таким образом, вы можете принимать символы из любого набора символов и хранить их как ISO-8859-1 (потому что Base64 выведет подмножество набора символов ASCII, который точно соответствует ISO-8859-1). Кодировка Base64 увеличит длину строки, в среднем, на 37%

Если ваши данные будут отображаться только как HTML, вы также можете хранить объекты HTML, как вы предлагали, но имейте в виду, что один объект может составлять до 10 символов на незакодированный символ, например& Thetasym; является ϑ

0

мне пришлось столкнуться с этой проблемой: «?» в Латиноамериканские специальные символы хранятся в виде или «¿» в моей базе данных Oracle ... Я не могу изменить NLS_CHARACTER_SET, потому что мы не являемся владельцами баз данных.

Итак, я нашел обходной путь:

1) код ASP.NET Создать функцию, которая преобразует строку шестнадцатеричных символов:

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) Использование функции выше переменной, которую вы хотите кодировать, как этот

 myVariableHex = ConvertirStringZHex(myVariable); 

в ORACLE, используйте следующее:

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

Конечно, iTEXTO - это параметр Oracle, который получает значение «myVariableHex» из кода ASP.NET.

Надеюсь, что это поможет ... если есть что-то, чтобы улучшить PLS, не стесняйтесь оставлять комментарии.

Источники: http://www.nullskull.com/faq/834/convert-string-to-hex-and-hex-to-string-in-net.aspx https://forums.oracle.com/thread/44799

Смежные вопросы