I am trying to set a very simple session connection variable on MySQL, but it doesn't do anything. The queries run below do not cause any errors, but the character set of the MySQL connection won't be changed. If I configure the default values for 'collation_server' and 'character_set_server' in the my.ini file as utf8mb4 instead of latin1, then the character set becomes utf8mb4, but I wonder why I cannot change the connection character set from my PHP script.
$pdo = new \PDO("mysql:host=localhost", "root", "");
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->query("SET NAMES utf8mb4");
print_r($pdo->query("SHOW GLOBAL VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';")->fetchAll(PDO::FETCH_ASSOC));
This query shows that the SET NAMES statement did not have affect.
You must use SHOW SESSION VARIABLES to see the changes, not SHOW GLOBAL VARIABLES.
SET NAMES doesn't change GLOBAL variables. It only changes the character set variables for your current session.
https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html says:
A SET NAMES 'charset_name' statement is equivalent to these three statements:
SET character_set_client = charset_name;
SET character_set_results = charset_name;
SET character_set_connection = charset_name;
Those statements change session variables only.
You are setting the charset for the session (not global). Try
SHOW SESSION VARIABLES WHERE ...
Note that with PDO you can set the character set as part of the DSN:
$pdo = new \PDO("mysql:host=localhost;charset=utf8mb4", "root", "");
Related
This question already has answers here:
UTF-8 all the way through
(13 answers)
Closed 3 years ago.
I can't understand whats problem.
I write data to mysql with php and utf-8 issues
Write in HTML form Binəqədi r. Çiçək qəs
Writed database Bin?q?di r. ÃÃÂ
When I use mysqli_set_charset($conn,"utf8"); in insert and update query
Writed database Bin?q?di r. Çiç?k q?s
Write data manually direct to database and use mysqli_set_charset($conn,"utf8"); in select works normal.
How can I fix it? INSERT and UPDATE with UTF-8.
This is my insert code
public function insert($sql) {
$conn = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
mysqli_set_charset($conn,"utf8");
// $conn->set_charset("utf8"); use same this.
if ($conn->query($sql) === TRUE) {
return 1;
} else {
return 0;
}
$conn->close();
}
NOTE: This issues on Linux and OSX. In windows work goods. How can I fix it for linux hosting?
try
AddDefaultCharset utf-8
in you apache configuration
or in you php file use
header( 'content-type: text/html; charset=utf-8' );
and also try to
default_charset = "utf-8";
in you php.ini
also you can try with
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character-set-client-handshake = false #force encoding to uft8
character-set-server=utf8
collation-server=utf8_general_ci
[mysqld_safe]
default-character-set=utf8
in your my.ini and restart mysql demon
Please consider all of these:
Before your queries, do this:
$conn->query('SET NAMES utf8');
Be sure your file encoding is utf8 (not the html encoding). I mean the file encoding which your IDE is using.
Be sure about your table charset
This is clearly a duplicate of a well-known issue, but cannot be flagged for closure due to the bounty. So, the checklist:
Ensure database columns, tables, and database are set to character set utf8mb4
Ensure the connection is set to the same character set with $conn->set_charset("utf8mb4");
Ensure your server is configured to inform web browsers that it will be sending Unicode text. In PHP, do header("Content-Type: text/html;charset=utf8"); or set it up in your web server configuration.
Try using set names
public function insert($sql) {
$conn = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// $conn->set_charset("utf8");
$conn->query("SET NAMES 'utf8'");
if ($conn->query($sql) === TRUE) {
return 1;
} else {
return 0;
}
$conn->close();
}
From MySQL (http://dev.mysql.com/doc/refman/5.7/en/charset-connection.html):
SET NAMES 'charset_name' [COLLATE 'collation_name']
SET NAMES indicates what character set the client will use to send SQL statements to the server. Thus, SET NAMES 'cp1251' tells the server, “future incoming messages from this client are in character set cp1251.” It also specifies the character set that the server should use for sending results back to the client. (For example, it indicates what character set to use for column values if you use a SELECT statement.)
A SET NAMES 'charset_name' statement is equivalent to these three statements:
SET character_set_client = charset_name;
SET character_set_results = charset_name;
SET character_set_connection = charset_name;
Setting character_set_connection to charset_name also implicitly sets collation_connection to the default collation for charset_name. It is unnecessary to set that collation explicitly. To specify a particular collation, use the optional COLLATE clause:
SET CHARACTER SET charset_name
SET CHARACTER SET is similar to SET NAMES but sets character_set_connection and collation_connection to character_set_database and collation_database. A SET CHARACTER SET charset_name statement is equivalent to these three statements:
SET character_set_client = charset_name;
SET character_set_results = charset_name;
SET collation_connection = ##collation_database;
Setting collation_connection also implicitly sets character_set_connection to the character set associated with the collation (equivalent to executing SET character_set_connection = ##character_set_database). It is unnecessary to set character_set_connection explicitly.
My opinion is that in some point the proper character set for the field description is not specified when using stored procedure. Do check again that your database/table/field have as character set utf8_general_ci
From MySQL (http://dev.mysql.com/doc/refman/5.7/en/charset-connection.html):
Example: Suppose that column1 is defined as CHAR(5) CHARACTER SET latin2. If you do not say SET NAMES or SET CHARACTER SET, then for SELECT column1 FROM t, the server sends back all the values for column1 using the character set that the client specified when it connected. On the other hand, if you say SET NAMES 'latin1' or SET CHARACTER SET latin1 before issuing the SELECT statement, the server converts the latin2 values to latin1 just before sending results back. Conversion may be lossy if there are characters that are not in both character sets.
The gibberish you displayed seems to involve more than one error. Çiç, when Mojibaked to latin1 gives Çiç.
Please provide SELECT col, HEX(col) FROM ... for something that is 'bad'.
Meanwhile, your reply about the stored procedure -- Do SHOW CREATE PROCEDURE ... and check what character set was in effect when the procedure was created. That could be part of the problem. (I noticed that that decade-old bug report you mentioned failed to consider this aspect.)
Having an issue with strange characters showing up when inserting into a database, have tried tirelessly to figure out the issue but I am out of ideas...
Basically if I insert this data like so (this is just testing):
$valy = "…industry's favorite </em><strong><em>party of the year</em></strong><em>, </em><a href='http://www.unitingagainstlungcancer.org/getinvolved/strolling-supper-with-blues-news'><span class='s1'><em>Joan's…";
$valy = mysql_real_escape_string($valy);
$query = "INSERT INTO test_table (data) VALUES ('".$valy."')";
mysql_query($query,$dbhandle);
this will end up in the database (notice the A characters):
"...industry's favorite party of the year, http://www.unitingagainstlungcancer.org/getinvolved/strolling-supper-with-blues-news'>Joan's..."
I have tried to line up all the character settings:
php default_charset = utf-8
mysql table & row charset = utf-8
Mysql instance variables:
character set client utf8
(Global value) latin1
character set connection utf8
(Global value) latin1
character set database latin1
character set filesystem binary
character set results utf8
(Global value) latin1
character set server latin1
character set system utf8
What could this issue be?
One thing you may be missing is when you setup the connection. There you should also set the encoding to utf8.
Example:
$link = mysql_connect('localhost', 'user', 'password');
mysql_set_charset('utf8',$link);
However, don't use the mysql extension, it's deprecated: http://php.net/manual/en/function.mysql-set-charset.php
Try to set the mysql connection to UTF-8 as well:
mysql_query("SET NAMES 'utf8'");
At first we was using the default character set by the mysql that was latin1_swedish_ci. Then we had problem with other languages like russian etc. So we have now converted the tables into collation and the field into utf8_unicode_ci. We need some confirmation here should we stick with utf8_unicode_ci for the support all the possible languages or go for something else like utf8_bin?
Next issue for php files where we are using mysqli we have set this.
if (!mysqli_set_charset($link, "utf8")) {
echo("Error loading character set utf8: ". mysqli_error($link));
}
else {
echo("Current character set: ". mysqli_character_set_name($link));
}
Then for places where we use mysql only we did as below
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET COLLATION_CONNECTION = 'utf8_unicode_ci'");
The problem now we find this is like quite tedious and we are scared we might be miss. Is it possible to set this character setting in like a config file like we have one for our db connection?
Don't mix mysql_* with mysqli_* functions. You need to stay consistent! You use mysqli_ first and then you use mysql_. That won't work!
This is how I do it:
mysqli_set_charset($Handle, 'utf8'); // <- add this too
mysqli_query($Handle, "SET NAMES 'utf8';");
mysqli_query($Handle, "SET CHARACTER SET 'utf8';");
mysqli_query($Handle, "SET COLLATION_CONNECTION = 'utf8_unicode_ci';");
// might be a bit redundant but it's safe :) ... I think :)
Then make sure you provide proper UTF8 to it.
I've made a simple PHP page to get the POST data and fetch a sql query then print the result. I'm using the mysql_fetch_array function.
The code works great but the response is a non-Unicode text, and it returns something like this:
?????ABC?????
note that the database collation is UTF8 and data stored are shown correctly in phpMyAdmin. I even used this META tag in php page but it results the same:
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
Any idea?!
Add these lines of code before the first query:
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET SESSION collation_connection = 'utf8_unicode_ci'");
Or you can edit your mysql configuration to use utf8 by default. Check here for what you need to do.
Change MySQL default character set to UTF-8 in my.cnf?
UPDATE
The function mysql_query is deprecated, so mysqli object can be used like so:
$mysqli = new mysqli("localhost", "MYSQL_USER", "MYSQL_PASS", "MYSQL_DB");
$mysqli->query("SET NAMES 'utf8'");
$mysqli->query("SET CHARACTER SET utf8");
$mysqli->query("SET SESSION collation_connection = 'utf8_unicode_ci'");
mysql_set_charset('utf8', $link);
Where $link is a connection created with mysql_connect
Try using mb_internal_encoding("UTF-8"); for details http://php.net/manual/en/function.mb-internal-encoding.php
I'm fetching data in Arabic from MySQL tables with MySQLi. So I usually use this in procedural style:
mysql_query("SET NAMES 'utf8'");
mysql_query('SET CHARACTER SET utf8');
Now I am using the OOP style so I am trying to see if there is something I could set rather than the above?
I only found this in PHP manual so I did it, but what about setting names to UTF8?
$mysqli->set_charset("utf8");
It's the same:
$mysqli->query("SET NAMES 'utf8'");
From the manual:
This is the preferred way to change the charset. Using mysqli::query()
to execute SET NAMES .. is not recommended.
$mysqli->set_charset("utf8"); is just enough, let the mysqli db driver do the thing for you.
You should use
$mysqli->set_charset("utf8");
Don't use SET NAMES or SET CHARACTER SET explicitly when using MySQLi., and certainly don't use both like the question asker here originally was. Reasons that this is a bad idea:
Calling SET CHARACTER SET utf8 after SET NAMES utf8 actually just undoes some of the work that SET NAMES did.
The PHP manual explicitly warns us to use mysqli_set_charset, not SET NAMES:
This is the preferred way to change the charset. Using mysqli_query() to set it (such as SET NAMES utf8) is not recommended. See the MySQL character set concepts section for more information.
Under the hood, mysqli_set_charset is just a wrapper for mysql_set_character_set from the MySQL C API (or its mysqlnd equivalent). Looking at the docs for that function, we can see the difference between it and SET NAMES:
This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
In other words, $mysqli->set_charset('foo') will do everything SET NAMES foo does and also ensure that mysqli_real_escape_string respects the new encoding. Admittedly, if you're only using encodings like Latin 1 and UTF 8 that strictly extend ASCII (that is, which encode all ASCII strings exactly as they would be encoded in ASCII), then using SET NAMES instead of set_charset won't break anything. However, if you're using more unusual encodings like GBK, then you could end up garbling your strings or even introducing SQL injection vulnerabilities that bypass mysqli_real_escape_string.
It's thus good practice to only use set_charset, not SET NAMES. There's nothing that SET NAMES does that set_charset doesn't, and set_charset avoids the risk of mysqli_real_escape_string behaving incorrectly (or even insecurely).
You can use this. Its realy nice for mysqli Character Set
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "dbpass";
$dbname = "dbname";
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
mysqli_query($conn,"SET CHARACTER SET 'utf8'");
mysqli_query($conn,"SET SESSION collation_connection ='utf8_unicode_ci'");
For procedural style lovers.
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
/* change character set to utf8 */
mysqli_set_charset($conn,"utf8");
mysqli_query($conn,"SET NAMES 'latin5'");
$conn = connection string