Maurice
Maurice

Reputation: 4940

PHP + SQL Server - How to set charset for connection?

I'm trying to store some data in a SQL Server database through php.

Problem is that special chars aren't converted properly. My app's charset is iso-8859-1 and the one used by the server is windows-1252.

Converting the data manually before inserting doesn't help, there seems to be some conversion going on.

Running the SQL query 'set char_convert off' doesn't help either.

Anyone have any idea how I can get this to work?

EDIT: I have tried ini_set('mssql.charset', 'windows-1252'); as well, but no result with that one either.

Upvotes: 25

Views: 101664

Answers (13)

Bud Damyanov
Bud Damyanov

Reputation: 31919

I did not notice someone to mention another way of converting results from MSSQL database. The good old iconv() function:

iconv (string $in_charset, string $out_charset, string $str): string;

In my case everything else failed to provide meaningful conversion, except this one when getting the results. Of course, this is done inside the loop of parsing the results of the query - from CP1251 to UTF-8:

foreach ($records as $row=>$col) {
    $array[$row]['StatusName'] = iconv ('CP1251', 'UTF-8' , $records[$row]['StatusName']);
}

Ugly, but it works.

Upvotes: 2

Donovan P
Donovan P

Reputation: 641

In my case, It worked after I added the "CharacterSet" parameters into sqlsrv_connect() connection's option.

$connectionInfo = array( 
        "Database"=>$DBNAME,
        "ConnectionPooling"=>0,
        "CharacterSet"=>"UTF-8"
);
$LAST_CONNECTION = sqlsrv_connect($DBSERVER, $connectionInfo);

See documentation here : https://learn.microsoft.com/en-us/sql/connect/php/connection-options?view=sql-server-2017

Upvotes: 3

Maja S.
Maja S.

Reputation: 1

Just adding ini_set('mssql.charset', 'UTF-8'); didn't help me in my case. I had to specify the UTF-8 character set on the column:

$age = 30;  
$name = utf8_encode("Joe");    

$select = sqlsrv_query($conn, "SELECT * FROM Users WHERE Age = ? AND Name = ?",
    array(array($age), array($name, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('UTF-8')));

Upvotes: 0

achos
achos

Reputation: 1

You should set the charset with ini_set('mssql.charset', 'windows-1252') before the connection. If you use it after the mssql_connect it has no effect.

Upvotes: 0

Attila Fulop
Attila Fulop

Reputation: 7011

If ini_set('mssql.charset', 'UTF-8'); doesn't help AND you don't have root access to modify the system wide freetds.conf file, here's what you can do:

1. Set up /your/local/freetds.conf file:

[sqlservername]
    host=192.168.0.56
    port=1433
    tds version=7.0
    client charset=UTF-8

2. Make sure your connection DSN is using the servername, not the IP:

'dsn' => 'dblib:host=sqlservername;dbname=yourdb

3. Make FreeTDS to use your local freetds.conf file as an unprivileged user from php script via env variables:

putenv('FREETDSCONF=/your/local/freetds.conf');

Upvotes: 5

bohdanbobrowski
bohdanbobrowski

Reputation: 21

For me editing this file:
/etc/freetds/freetds.conf
...and changing/setting 'tds version' parameter to '7.0' helped. Edit your freetds.conf and try to change this parameter for your server configuration (or global).

It will work even without apache restart.

Upvotes: 2

chugadie
chugadie

Reputation: 2883

If you are using TDS protocol version 7 or above, ALL communications over the wire are converted to UCS2. The server will convert from UCS2 into whatever the table or column collation is set to, unless the column is nvarchar or ntext. You can store UTF-8 into regular varchar or text, you just have to use a TDS protocol version lower than 7, like 6.0 or 4.2. The only drawback with this method is that you cannot query any nvarchar, ntext, or sys.* tables (I think you also can't do any CAST()ing) - as the server refuses to send anything that might possibly be converted to UTF-8 to any client using protocol version lower than 7.

It is not possible to avoid converting character sets when using TDS protocol version 7 or higher (roughly equivalent to MSSQL 2005 or newer).

Upvotes: 4

Mano Kovacs
Mano Kovacs

Reputation: 1514

Client charset is necessary but not sufficient:

ini_set('mssql.charset', 'UTF-8');

I searched for two days how to insert UTF-8 data (from web forms) into MSSQL 2008 through PHP. I read everywhere that you can't, you need to convert to UCS2 first (like cypher's solution recommends). On Windows SQLSRV said to be a good solution, which I couldn't try, since I am developing on Mac OSX.

However, FreeTDS manual (what PHP mssql uses on OSX) says to add a letter "N" before the opening quote:

mssql_query("INSERT INTO table (nvarcharField) VALUES (N'űáúőűá球最大的采购批发平台')", +xon);

According to this discussion, N character tells the server to convert to Unicode. https://softwareengineering.stackexchange.com/questions/155859/why-do-we-need-to-put-n-before-strings-in-microsoft-sql-server

Upvotes: 25

Jaime Neto
Jaime Neto

Reputation: 61

I had the same problem and ini_set('mssql.charset', 'utf-8') did not work for me. However, it worked in uppercase:

ini_set('mssql.charset', 'UTF-8');

Upvotes: 6

Matthew Setter
Matthew Setter

Reputation: 2447

I suggest looking at the following points:

  1. Ensure that the columns that you're storing the information in are nchar or nvarchar as char and nvarchar don't support UCS-2 (SQLServer doesn't store in UTF-8 format btw)
  2. If you're connecting with the mssql library/extension for PHP, run: ini_set('mssql.charset', 'utf-8'); as there's no function with a charset argument (connect, query etc)
  3. Ensure that your browsers charset is also set to UTF-8

Upvotes: 5

Jacob Honeyhume
Jacob Honeyhume

Reputation: 1965

I've had luck in a similar situation (using a PDO ODBD connection) using the following code to convert the encoding before printing output:

$data = mb_convert_encoding($data, 'ISO-8859-1', 'windows-1252');

I had to manually set the source encoding, because it was erroneously being reported as 'ISO-8859-1' by mb_detect_encoding().

My data was also being stored in the database by another application, so I might be in a unique situation, although I hope it helps!

Upvotes: 3

Sandro Gržičić
Sandro Gržičić

Reputation: 313

Can't you just convert your tables to your application encoding? Or use utf-8 in both?

I don't know whether MSSQL supports table-level encodings, though.

Also, try the MB (multibyte) string functions, if the above fails.

Upvotes: 0

mck89
mck89

Reputation: 294

You can use the mysql_set_charset function: https://www.php.net/manual/en/function.mysql-set-charset.php

Upvotes: -4

Related Questions