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

94,761

Solution 1

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

Solution 2

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

Solution 3

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

Solution 4

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

Solution 5

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

Share:
94,761

Related videos on Youtube

Maurice
Author by

Maurice

Updated on July 09, 2022

Comments

  • Maurice
    Maurice almost 2 years

    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.

    • VolkerK
      VolkerK almost 15 years
      mssql.charset is only available with FreeTDS. Does this config parameter show up in phpinfo() on your server?
    • Maurice
      Maurice almost 15 years
      Yes, it does show up. Phpinfo also states that the MSSQL Library version is FreeTDS. local value: windows-1252 master value: no value
  • VolkerK
    VolkerK almost 15 years
    mysql_set_charset is for MySQL, but the question mentions mssql (sql server) two times.
  • Maurice
    Maurice almost 15 years
    Unfortunately, I can't. For it is not my database, and it's not my framework either. Converting special characters to entities is not an option either, since there is some non-web software connected to this db aswell. I'm used to converting with iconv, but I'll give MB a try.
  • Maurice
    Maurice almost 15 years
    Same results with mb. It seems there is some automatic conversion done while sending data to db.
  • Matthew Setter
    Matthew Setter over 12 years
    Also, if you're using Zend_Db, then don't forget about the charset parameter when initialising the connection:...params.charset = "utf8"
  • John Kary
    John Kary over 10 years
    On a Linux system you can set this TDS protocol version in freetds.conf by specifying the following options under the parameter grouping [global] -- tds version = 8.0 client charset = UTF-8 See: gist.github.com/johnkary/6643856
  • Yarimadam
    Yarimadam almost 6 years
    Wasted 3 hours on this. Thank you!
  • delphirules
    delphirules over 5 years
    Thank you, i wasted 3 DAYS on this issue ! o/
  • eduardo a
    eduardo a about 5 years
    This works in my case, SQL Server 2014 and PHP 7.3 running on Windows Server