PDO DBLIB многобайтовая (китайская) кодировка символов - SQL-сервер
На машине Linux я использую PDO DBLIB для подключения к базе данных MSSQL и вставки данных в таблицу SQL_Latin1_General_CP1_CI_AS
. Проблема в том, что когда я пытаюсь вставить китайские символы (многобайтовые), они вставляются как å"ˆå¸‚香åŠåŒºç 江路å·
.
Мой (часть) кода выглядит следующим образом:
$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);
Что я пробовал до сих пор:
-
Выполнение mb_convert_encoding
до UTF-16LE
на $firstname
и CAST как VARBINARY в запросе типа:
$firstname = mb_convert_encoding($firstname, 'UTF-16LE', 'UTF-8');
VALUES
(CAST(:firstname AS VARBINARY));
Это приводит к правильной вставке символов, пока не появятся некоторые не-многобайтовые символы, которые прерывают выполнение PDO.
-
Настройка моего подключения как 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");
-
Установка client charset
в UTF-8 в моем freetds.conf
Это не повлияло.
Есть ли вообще способ вставить многобайтовые данные в эту базу данных SQL? Есть ли другой способ обхода? Я думал о том, чтобы попробовать PDO ODBC или даже mssql, но подумал, что лучше спросить здесь, прежде чем тратить больше времени.
Спасибо заранее.
EDIT:
В итоге я использовал MSSQL и префикс типа N
. Я поменяю местами и попробую PDO_ODBC, когда у меня будет больше времени. Спасибо всем за ответы!
Ответы
Ответ 1
Есть ли вообще способ вставить многобайтовые данные в [этот конкретный] SQL база данных? Есть ли другой способ обхода?
-
Если вы можете переключиться на PDO_ODBC, Microsoft предоставляет бесплатные драйверы ODBC для SQL Server для Linux (только для 64-разрядных Red Hat Enterprise Linux и 64-разрядных SUSE Linux Enterprise), которые поддерживают Unicode.
/li > -
Если вы можете перейти на PDO_ODBC, тогда N-префикс для вставки Юникода будет работать.
-
Если вы можете изменить затронутую таблицу с SQL_Latin1_General_CP1_CI_AS
на UTF-8
(которая по умолчанию используется для MSSQL), тогда это будет идеально.
Ваше дело более ограничено. Это решение подходит для случая, когда у вас смешанные многобайтовые и многобайтовые символы в вашей строке ввода, и вам нужно сохранить их в латинской таблице, а префикс типа N
не работает, t хочет отказаться от PDO DBLIB (поскольку Microsoft Unicode PDO_ODBC едва поддерживается в 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!
Ответ 2
Учет не должен иметь значения здесь.
Двухбайтовые символы должны храниться в полях nvarchar
, nchar
или ntext
. Вам не нужно выполнять кастинг.
Префикс типа n
обозначает "Национальный", и он заставляет SQL Server хранить текст в виде Unicode (UTF-16).
Edit:
PDO_DBLIB не поддерживает Unicode и теперь устарел.
Если вы можете переключиться на PDO_ODBC, Microsoft предоставляет бесплатные драйверы ODBC для SQL Server для Linux, которые поддерживают Unicode.
Документация драйвера Microsoft - SQL Server ODBC
Блог - установка и использование драйвера ODBC Microsoft SQL Server для Linux
Ответ 3
Вы можете использовать Unicode-совместимый тип данных для столбца таблицы для поддержки иностранных языков (исключения показаны в EDIT 2).
(char, varchar, text) Versus (nchar, nvarchar, ntext)
Не-Юникод:
Лучше всего подходит для английского языка США: "Одна проблема с типами данных, которые используют 1 байт для кодирования каждого символа, состоит в том, что тип данных может содержать только 256 разных символов. Это заставляет использовать несколько спецификаций кодирования (или кодовых страниц) для разных алфавитов, таких как Европейские алфавиты, которые относительно малы, также невозможно обрабатывать такие системы, как японские алфавиты кандзи или корейский хангул, которые имеют тысячи символов
Unicode
Лучше всего подходит для систем, которые должны поддерживать по крайней мере один иностранный язык: "Спецификация Unicode определяет единую схему кодирования для большинства символов, широко используемых в компаниях по всему миру. Все компьютеры последовательно преобразуют битовые шаблоны в данные Unicode в символы, используя единственная спецификация Юникода, которая гарантирует, что один и тот же бит-шаблон всегда будет преобразован в один и тот же символ на всех компьютерах. Данные могут свободно переноситься из одной базы данных или компьютера в другую, не опасаясь, что принимающая система неправильно преобразует битовые шаблоны в символы.
Пример:
Также я попробовал один пример, который вы можете просмотреть на его экранах ниже, это было бы полезно для вопросов, связанных с вставками иностранных языков, поскольку вопрос прямо сейчас. Столбец, как показано ниже в nvarchar
, и он поддерживает китайский язык
![enter image description here]()
ИЗМЕНИТЬ 1:
Обсуждается другая связанная с этим проблема здесь
ИЗМЕНИТЬ 2:
Unicode неподдерживаемые скрипты отображаются здесь
Ответ 4
просто используйте nvarchar, ntext, nChar и когда вы хотите вставить
использовать
INSERT INTO UserSignUpInfo
(FirstName)
VALUES
(N'firstname');
N
будет ссылаться на Unicode charactor и является стандартным во всем мире.
Ссылка:
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/
Ответ 5
Эта ссылка Объясните китайский символ в MYSQL. Невозможно вставить китайский символ в MySQL.
Вы должны создать таблицу table_name() CHARACTER SET = utf8;
Use UTF-8
при вставке в таблицу
set username utf8; INSERT INTO table_name (ABC,VAL);
abd создать базу данных в CHARACTER SET utf8 COLLATE utf8_general_ci;
то вы можете вставить китайский символ в таблицу