2015-02-26 2 views
14

На машине Linux я использую PDO DBLIB для подключения к базе данных MSSQL и вставки данных в таблицу SQL_Latin1_General_CP1_CI_AS. Проблема в том, что когда я пытаюсь вставить китайские символы (многобайтовые), они вставлены как 哈市香åŠåŒºç æ±Ÿè·¯å·.PDO DBLIB многобайтовая (китайская) кодировка символов - SQL-сервер

My (часть) код выглядит следующим образом:

$DBH = new PDO("dblib:host=$myServer;dbname=$myDB;", $myUser, $myPass); 

$query = " 
    INSERT INTO UserSignUpInfo 
    (FirstName) 
    VALUES 
    (:firstname)"; 

$STH = $DBH->prepare($query); 

$STH->bindParam(':firstname', $firstname); 

То, что я пытался до сих пор:

  1. Ведение mb_convert_encoding к UTF-16LE на $firstname и CAST, как VARBINARY в запросе, как :

    $firstname = mb_convert_encoding($firstname, 'UTF-16LE', 'UTF-8');

    VALUES 
    (CAST(:firstname AS VARBINARY)); 
    

    Который приводит к правильному введению символов, пока не появятся некоторые не-многобайтовые символы, которые нарушают выполнение PDO.

  2. Установка мое подключение как utf8:

    $DBH = new PDO("dblib:host=$myServer;dbname=$myDB;charset=UTF-8;", $myUser, $myPass); 
    $DBH->exec('SET CHARACTER SET utf8'); 
    $DBH->query("SET NAMES utf8"); 
    
  3. client charset Установка в UTF-8 в моем freetds.conf

    который не имел никакого влияния.

Есть ли вообще способ вставить многобайтовые данные в эту базу данных SQL? Есть ли другой способ обхода? Я думал о том, чтобы попробовать PDO ODBC или даже mssql, но подумал, что лучше спросить здесь, прежде чем тратить больше времени.

Заранее спасибо.

EDIT:

Я закончил с использованием MSSQL и префикс типа в N данных. Я поменяю местами и попробую PDO_ODBC, когда у меня будет больше времени. Спасибо всем за ответы!

+0

Извините за вопрос, но несколько раз сверки поля отличается от сортировки таблицы, так что я хочу знать, ** типа ** и * * сортировка ** вашего поля; плз. –

+1

Вы тестируете 'nvarchar()' или 'ntext'? –

+0

Согласно [this] (http://php.net/manual/en/ref.pdo-dblib.php#109439) вы можете сначала преобразовать данные, а затем вставить. Ссылка делает что-то вроде этого: '$ STH-> bindValue (': value', iconv ('UTF-8', 'ISO8859-1', $ value));'. Это похоже на первый пункт вашего вопроса в разделе «Что я пробовал до сих пор».Я не понимаю, какой тип столбца вы вставляете, поэтому это может не сработать. –

ответ

8

Есть ли вообще способ вставить многобайтовые данные в [эту конкретную] базу данных SQL ? Есть ли другой способ обхода?

  1. Если вы можете переключиться на PDO_ODBC, Microsoft предоставляет бесплатно SQL драйверов ODBC сервера для Linux (только для 64-битной Red Hat Enterprise Linux и 64-битной SUSE Linux Enterprise), которые поддерживают Unicode.

  2. Если вы можете перейти на PDO_ODBC, тогда N-префикс для вставки Unicode будет работать.

  3. Если вы можете изменить затронутую таблицу от SQL_Latin1_General_CP1_CI_AS до UTF-8 (что является значением по умолчанию для MSSQL), то это было бы идеально.

Ваш случай более ограничен. Это решение подходит для случая, когда у вас смешанные многобайтовые и многобайтовые символы в вашей строке ввода, и вам необходимо сохранить их в латинской таблице, а префикс типа N не работает, и вы не хотите чтобы отказаться от PDO DBLIB (поскольку Microsoft Unicode PDO_ODBC равен barely supported на linux). Вот один способ обхода.

Условно кодировать входную строку как base64. В конце концов, так мы можем безопасно транспортировать фотографии в соответствии с электронными письмами.

Рабочий пример:

$DBH = new PDO("dblib:host=$myServer;dbname=$myDB;", $myUser, $myPass); 

$query = " 
INSERT INTO [StackOverflow].[dbo].[UserSignUpInfo] 
      ([FirstName]) 
    VALUES 
      (:firstname)"; 

$STH = $DBH->prepare($query); 

$firstname = "输入中国文字!Okay!"; 

/* First, check if this string has any Unicode at all */ 
if (strlen($firstname) != strlen(utf8_decode($firstname))) { 
    /* If so, change the string to base64. */ 
    $firstname = base64_encode($firstname); 
} 

$STH->bindParam(':firstname', $firstname); 
$STH->execute(); 

Затем идти в обратном направлении, вы можете проверить base64 строки и декодировать только их без повреждения существующих записей, например, так:

while ($row = $STH->fetch()) { 
    $entry = $row[0]; 

    if (base64_encode(base64_decode($entry , true)) === $entry) { 

     /* Decoding and re-encoding a true base64 string results in the original entry */ 
     print_r(base64_decode($entry) . PHP_EOL); 

    } else { 

     /* Previous entries not encoded will fall through gracefully */ 
     print_r($entry . PHP_EOL); 
    } 
} 

Записи будут сохранены следующим образом:

Guan Tianlang 
5pys6Kqe44KS5a2maGVsbG8= 

Но вы можете легко конвертировать их обратно:

Guan Tianlang 
输入中国文字!Okay! 
+1

Большое спасибо за ваше усилие в написании этого ответа! К сожалению, система, которая извлекает данные после их хранения в БД, находится на .NET, и у меня нет доступа. Тем не менее, это сладкое обходное решение. – Manolis

-2

Эта ссылка Объясните китайский символ в MYSQL. Can't insert Chinese character into MySQL. Вы должны создать таблицу table_name() CHARACTER SET = utf8; Use UTF-8 при вставке в таблицу

set username utf8; INSERT INTO table_name (ABC,VAL); 

абд создать базы данных в CHARACTER SET utf8 COLLATE utf8_general_ci;

Вы можете вставить в китайский символ в таблице

+0

Таблица 'SQL_Latin1_General_CP1_CI_AS' и, к сожалению, ее нельзя изменить - она ​​является частью огромной корпоративной системы. – Manolis

+0

'mysql_query (« SET character_set_client = utf8 », $ dbLink) или умереть (mysql_error()); mysql_query ("SET character_set_connection = utf8", $ dbLink) или умереть (mysql_error()); 'попробуйте вот так – ABIRAMAN

+1

Это запрос MySQL. Я работаю над MSSQL – Manolis

2

Collation не должен вопрос здесь.

Двухбайтовые символы должны храниться в nvarchar, nchar, или ntext. Вам не нужно выполнять кастинг.

Префикс типа данных n обозначает National, и SQL Server хранит текст в виде Unicode (UTF-16).

Edit:

PDO_DBLIB не поддерживает Unicode, и в настоящее время не рекомендуется.

Если вы можете переключиться на PDO_ODBC, Microsoft предоставляет бесплатные драйверы ODBC для SQL Server для Linux, которые поддерживают Unicode.

Microsoft - SQL Server ODBC Driver Documentation

Blog - Installing and Using the Microsoft SQL Server ODBC Driver for Linux

+0

Просто попробовал использовать mssql_query с PHP и N '' и он работал нормально. Интересно, есть ли способ сделать PDO_DBLIB таким же ... – Manolis

+0

В этой статье на php.net говорится, что PDO_DBLIB устарел и рекомендует использовать SqlSrv в Windows и PDO_ODBC в другом месте. http://php.net/manual/en/ref.pdo-dblib.php. Можете ли вы попробовать PDO_ODBC? –

+0

Хотя это может быть устаревшим, это не очень помогает OP с PDO_DBLIB. Сначала он ищет обходное решение. – Drakes

-1

просто использовать NVARCHAR, NTEXT, NCHAR и когда вы хотите, чтобы вставить его Используйте

INSERT INTO UserSignUpInfo 
    (FirstName) 
    VALUES 
    (N'firstname'); 

N будет относиться к Charactor Unicode и является стандартом во всем мире.

Ref:

https://aalamrangi.wordpress.com/2012/05/13/storing-and-retrieving-non-english-unicode-characters-hindi-czech-arabic-etc-in-sql-server/

https://technet.microsoft.com/en-us/library/ms191200(v=sql.105).aspx

https://irfansworld.wordpress.com/2011/01/25/what-is-unicode-and-non-unicode-data-formats/

+0

OP сказал: «Просто попробовал использовать mssql_query с PHP и N», и он работал нормально. Интересно, есть ли способ заставить PDO_DBLIB работать так, , Пожалуйста, внимательно прочитайте его другие комментарии. – Drakes

1

Вы можете использовать Unicode совместимый тип данных для столбца таблицы для поддержки иностранных языков (исключения приведены в EDIT 2).

(CHAR, VARCHAR, текст) Versus (NCHAR, NVARCHAR, NTEXT)

Non-Unicode:

Лучше всего подходит для американского английского языка: «Одна из проблем, с данными типы, которые используют 1 байт для кодирования каждого символа, это то, что тип данных может содержать только 256 разных символов, что приводит к множественным спецификациям кодирования (или кодовым страницам) для разных алфавитов, таких как европейские алфавиты, которые относительно малы. о обрабатывать такие системы, как японские кандзи или корейский хангыль алфавитов, которые имеют тысячи символов

Unicode

Лучше всего подходит для систем, которые должны поддерживать по крайней мере один иностранный язык: «Спецификация Unicode определяет единую кодировку схема для большинства персонажей, широко используемых в компаниях по всему миру. Все компьютеры последовательно преобразуют битовые шаблоны в данных Юникода в символы, используя единую спецификацию Юникода. Это гарантирует, что один и тот же бит-шаблон всегда будет преобразован в один и тот же символ на всех компьютерах. Данные могут свободно переноситься из одной базы данных или компьютера в другую, не опасаясь, что принимающая система неправильно преобразует битовые шаблоны в символы.

Пример:

Также я попробовал один пример вы можете просмотреть его экраны ниже, было бы полезно для вопросов, связанных с иностранного языка вставки, как вопрос прямо сейчас.Колонна, как показано ниже в nvarchar и поддерживают китайский язык

enter image description here

EDIT 1:

Другой связанный с этим вопрос обсуждается here

EDIT 2:

Unicode неподдерживаемые скрипты показаны here

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