« 無線網路對人體健康的影響 | 首頁 | Sendmail + MailScanner + ClamAV 安裝實錄 »

2005年01月19日

PHP@Linux vs MS-SQL Server database (using FreeTDS)

FreeTDS 提供一套函數庫, 讓執行於 Unix 與 Linux 環境的程式可以透過它存取 Microsoft SQL Server 與 Sybase database.
以下是讓 Linux 上的 PHP 可以透過 FreeTDS 存取 MSSQL Server 的操作步驟:

環境: Fedora Core 1 完全安裝 (已裝有 Apache HTTP Server + PHP + MySQL 的環境)

Step 1. 安裝 FreeTDS

FreeTDS 官方網站: http://www.freetds.org/ 選擇下載 FreeTDS source distribution

編譯參數: --prefix=/usr/local/freetds --enable-msdblib

安裝後, 修改 /etc/ld.so.conf, 加入 /usr/local/freetds/lib; 完成後再執行 ldconfig

Step 2. 修改 /usr/local/freetds/etc/freetds.conf

[sql2k]

host = your.mssql.server.ip
port = 1433
client charset = cp950
tds version = 8.0

a. 中括弧 [ ] 內的字串可自行定義, 往後連線時會用到.
b. tds version: 4.2 (適用 MS SQL Server 6.x); 7.0 (適用 7.x); 8.0 (適用 2000)

Step 3. 測試 FreeTDS 是否可連線 MS SQL Server

#cd /usr/local/freetds/bin
#./tsql -S sql2k -U sa
1> use mydatabase
2> select * from mytable
3> go

成功的話會顯示 mytable 資料

離開 tsql:

1> quit

Step 4. 重新編譯 PHP Source

PHP 官方網站: http://www.php.net/

編譯前, 先用 php 程式執行 echo phpinfo(); 顯示原本安裝時所有的參數, 以取用需要的 configure 參數
最後再加上 --with-mssql=/usr/local/freetds

執行範例:

./configure '--prefix=/usr/local/php_4.3.10' '--localstatedir=/var' '--disable-debug' '--enable-pic' '--disable-rpath' '--enable-inline-optimization' '--with-bz2' '--with-db4=/usr' '--with-curl' '--with-exec-dir=/usr/bin' '--with-freetype-dir=/usr' '--with-png-dir=/usr' '--with-gd' '--enable-gd-native-ttf' '--without-gdbm' '--with-gettext' '--with-ncurses' '--with-gmp' '--with-iconv' '--with-jpeg-dir=/usr' '--with-openssl' '--with-png' '--with-pspell' '--with-regex=system' '--with-xml' '--with-expat-dir=/usr' '--with-dom' '--with-dom-xslt=/usr' '--with-dom-exslt=/usr' '--with-xmlrpc=shared' '--with-pcre-regex=/usr' '--with-zlib' '--with-layout=GNU' '--enable-bcmath' '--enable-exif' '--enable-ftp' '--enable-magic-quotes' '--enable-safe-mode' '--enable-sockets' '--enable-sysvsem' '--enable-sysvshm' '--enable-track-vars' '--enable-trans-sid' '--enable-yp' '--enable-wddx' '--with-pear=/usr/share/pear' '--with-imap=shared' '--with-imap-ssl' '--with-kerberos' '--with-ldap=shared' '--with-mysql' '--with-pgsql=shared' '--with-snmp' '--with-snmp=shared' '--enable-ucd-snmp-hack' '--with-unixODBC' '--enable-memory-limit' '--enable-bcmath' '--enable-shmop' '--enable-calendar' '--enable-dbx' '--enable-dio' '--enable-mcal' '--enable-mbstring' '--enable-mbstr-enc-trans' '--enable-mbregex' '--with-apxs2=/usr/sbin/apxs' '--with-mssql=/usr/local/freetds'

編譯、安裝完成後, cp php.ini-dist /prefix/lib/php.ini

Step 5. 啟動 Apache HTTP Server 進行測試

Sample Code:

<?php

mssql_connect('sql2k','sa','');
mssql_select_db('mydatabase');
$rs = mssql_query('select * from mytable');
list($column01) = mssql_fetch_row($rs);
echo $column01;

?>

成功的話, 會顯示 mytable 第一筆資料的第一個欄位內容

mssql functions 請參見: http://tw2.php.net/manual/tw/ref.mssql.php

Posted by Jamyy at 2005年01月19日 21:27

Trackback Pings

TrackBack URL for this entry:
http://cha.homeip.net/cgi-bin/mt/mt-tb.cgi/39

Comments

想請教一下! 我現在是使用Apache2, FreeTDS, 和PHP去連MSSQL, 對方MSSQL存的方式為UTF-8, 我使用了多種方式(包括直接用FreeTDS連), 可是抓回來的都還是亂碼! 希望您能指點一下, 感恩!

Posted by: Yu-Ting at 2005年07月14日 16:00

您客氣了!
這問題應該是網頁 charset 的問題,
您可以試著在 <head>...</head> 之間加入:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
或是在 PHP 程式中, 於輸出前加入:
header('Content-Type:text/html; charset=utf-8');
看看是否能解決您的問題

Posted by: Jamyy at 2005年07月14日 17:53

先謝謝您的回覆!
小弟把/usr/local/freetds/etc/freetds.conf內
client charset改成您上面的CP950後,就可正確讀出
資料了,謝謝!但不知CP950是啥編碼?
謝謝

Posted by: Yu-Ting at 2005年07月15日 10:24

啊, 被發現了嗎? 那是我昨天才補上去的... 真是不好意思 ^^'

當初 po 這篇的時候沒測到中文資料的部份, 所以就沒發現 FreeTDS 在 query 中文資料的時候會出現問題, 一直到昨天為了測試您的問題才發現有這種狀況... 所以我也要謝謝您喲! :)

cp950 代表繁體中文字頁碼 (Code Page: 950; ANSI/OEM - Traditional Chinese Big5)

若您有興趣, 可以從 Windows 系統中找到更多的字頁碼對照資料:

Windows XP:
控制台→地區及語言選項→進階→字碼頁轉換表

Windows 2000:
開始→控制台→地區選項→一般→進階→字碼頁轉換表

Wikipedia 關於 Code Page 的闡述 (英文):
http://en.wikipedia.org/wiki/Code_page

Posted by: Jamyy at 2005年07月15日 11:09

版主您好:小弟照著的步驟做,用tql 做是可以正確的抓到資料,但是在測試時,用您的Sample Code時就出現Warning: mssql_connect(): WARNING! Some character(s) could not be converted into client's character set. Unconverted bytes were changed to question marks ('?'). (severity 16) in /home/httpd/html/test4.php on line 2
而freetds.conf中有加入cp950了,我的環境是用 trustix+php+apache連ms-sql2000的,請問一下,是我那邊沒有設定好嗎?

Posted by: ken at 2005年07月17日 00:40

不好意思,版主,剛忘了說清楚,我在tsql 中是直接用ip的,就可以,如果是用freetds.conf中定義的[sql2k]也是會出現
WARNING! Some character(s) could not be converted into client's character set. Unconverted bytes were changed to question marks ('?'). 的訊息!!

Posted by: ken at 2005年07月17日 02:04

您好!
我也是連結到 mssql 2000, 在 freetds.conf 還沒加入 client charset = cp950 之前, 執行 PHP 網頁時也是出現和你一樣的錯誤訊息, 不過在加入前述的設定值之後, 就沒有這個問題了.
以下是幾個關鍵的設定地方, 請您試試看調整後是否能解決您的問題:

1. httpd.conf ==> AddDefaultCharset off
2. locale ==> 除 LC_MESSAGES、LC_COLLATE、LC_TIME 之外, 其餘皆為 zh_TW
3. 瀏覽器重新載入網頁: Ctrl + F5 (強迫重新載入最新的網頁資料)

我的環境是:
freetds version: 0.62.4
php version: 4.3.10

Posted by: Jamyy at 2005年07月17日 21:32

謝謝版主的回覆,現在又出現一個新問題,就是Warning: mssql_connect(): Unable to connect to server: sql2k ,這是沒有連結上資料庫的訊息,mssql_connect('sql2k','sa','');我用這樣會出現,但改成用ip 的話就會出現
WARNING! Some character(s) could not be converted into client's character set. Unconverted bytes were changed to question marks ('?'). 的訊息了,不知是不是我的系統是用trustix 的原因?
而httpd.conf 的檔中,找不到你說的設定呢@!!

Posted by: ken at 2005年07月17日 23:21

mysql_connect('sql2k','sa','') 執行時出現 Unable to connect to server 錯誤訊息表示 freetds.conf 沒有 [sql2k] 這個設定, 或是 freetds.conf 裡的 [sql2k] 設定有問題, 您可以檢查一下 freetds.conf 看看. 如果您是照著本篇的安裝步驟的話, freetds.conf 的完整路徑是: /usr/local/freetds/etc/freetds.conf

而 mysql_connect('IP','sa','') 可以連結 mssql server, 可是卻出現 Some character(s) could not be converted 的問題可修改 freetds.conf 裡的 [global] 參數區, 加上 client charset = cp950 解決.

AddDefaultCharset 只在 Apache HTTP Server 1.3.12 (含)以後的版本才有這個設定.

Posted by: Jamyy at 2005年07月19日 09:54

版主您好~~~
請問一下~ mssql_select_db&mssql_query 在TRUSTIX上,可以連接中文名稱的dbase & table嗎? 我要連接中文名dbase一直是false,連接英文名的dbase就ok,不知道是不是中文的關係??在redhat上測,中英文都可以正確的抓到資料。

Posted by: Opal at 2005年07月19日 16:31

您好!
真的耶! 我在 Fedora Core 2 連結中文資料庫、中文表格、中文欄位, 然後顯示中文內容都沒問題:
<?php

mssql_connect('sql2k','sa');
mssql_select_db('[測試資料庫]');
$rs = mssql_query('select top 1 [欄位一] from [中文表格]');
list($col01) = mssql_fetch_row($rs);
echo $col01;

?>
不過我還沒用 Trustix 試過, 再找時間再幫您 try try 看囉~

Posted by: Jamyy at 2005年07月20日 09:20

不好意思, 原來 FreeTDS 在 Trustix 上真的和 FC2 差很多
以下是我在 Trustix 上測試的小小心得:
/blog/archives/2005/07/freetds_trustix.html
不過還是沒測出來如何讓 FreeTDS + PHP + MSSQL 在 Trustix 上顯示中文資料... ~>_<~

Posted by: Jamyy at 2005年07月21日 20:06

謝謝版主的分享^^

Posted by: Opal at 2005年07月26日 10:06

網主你好,無意間看到此網頁.

就是有個問題就是
執行 tsql -S sql2k -U sa
輸入密碼後便出現下面的英文
There was a problem connecting to the server

請問網主有沒有遇到此問題呢?我還不了解到底出在什麼地方@"@

Posted by: Shengeih at 2006年03月29日 12:20

Shengeih 您好,

這個訊息表示無法連結指定的 ms-sql server
請先檢查 freetds.conf 當中 [sql2k] 這個區塊的設定值
主要的連線參數是:
host = ms-sql server 內部 IP (如: 192.168.0.1)
port = ms-sql server 使用的 port (預設是 1433)
如果這兩個設定都沒問題, 就要檢查您的 ms-sql server 的設定是否有問題
或是網路 (如:防火牆) 的問題

Posted by: Jamyy at 2006年03月29日 14:02

相當感謝網主的提供解答,小弟深表感謝.

in freetds.conf 其設定都是正確的,但有發覺到不一樣的地方就是在 windows 上面的 SQL Server 2000 的機器上面執行 netstat -an 竟沒有看到 1433port ? 是否會是此問題呢? 因為此窗口沒有開啟的原因是什麼,我也不太曉得.
喔對,我的 Windows is XP Home Edit SP2

Posted by: Shengeih at 2006年03月29日 14:17

您客氣了
我有個印象,
就是 MS-SQL Server 2000 除了 "個人版" 之外
不能裝在 "非 Windows Server" 的機器上
所以您安裝的可能只有 Client Tools 而已
並沒有將 SQL Server 的部份裝進去
是不是這樣子呢?

Posted by: Jamyy at 2006年03月29日 15:59

我是在 Home 上面裝中文個人版,但也是可以使用 Enterprise Manager 來使用,但不知道是怎麼回事,好像有點怪異,不管如何!我已經整個 OS 要重新安裝來做 test...

是否有細節的差異,我會在寫上來做記錄或討論...感謝您.

Posted by: Shengeih at 2006年03月29日 16:01

我是用UTF-8
select查詢當碰到特殊字如 坂 堃 這種非標準big5內的擴充字就會出現
Warning: mssql_query() [function.mssql-query]: WARNING! Some character(s) could not be converted into client's character set. (severity 16) in /www/lib/php/adodb/drivers/adodb-mssql.inc.php on line 697
這種錯誤!
該欄就會是空白但確實是能搜尋到!

用mssql自己的管理工具去查特殊字的地方會空白一格顯示不出來!但確實有資料

監看 FreeTDS log 特殊字的查詢 sql 有正確送出!

安裝 Unicode補完計畫 在 Windows下的程式能讓這些特殊字顯示出來

所以這到底要怎樣才能透過web去list出含特殊字的資料呢?是 php mssql函式本身的問題嗎?

Posted by: 星夜如雨 at 2006年11月22日 12:36

若要使用 UTF-8, 請將環境設置如下:

1. MS-SQL 欄位型態使用 nvarchar 或 nchar
2. freetds.conf 的 client charset = UTF-8
3. HTML Header 設置 charset=UTF-8

Posted by: Jamyy at 2006年11月23日 11:22

板主你好,我照著一步一步來,很奇怪的是,
我如果不把 995 設定的話,他會出現編碼錯誤,而且抓到的資料會變為亂碼,但神奇的是,如果把client charset = cp950
設定道 freetds.conf 中的話 ,我就會連資料庫都沒辦法連到
這是為何?可有解QQ?

Posted by: akn at 2007年01月25日 17:26

不好意思, 我看不太懂你的問題
你是說設定了 client charset=cp950 之後
就沒法連到資料庫嗎?
如果有錯誤訊息的話比較好找出原因喔

Posted by: Jamyy at 2007年01月25日 22:01

台湾的同胞你好:
我现在也有 和你 一样的 问题:在 linux上用php存取windows 上的MSSQL Server。现在有这样的错误提示:Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 276480 bytes) in /opt/lampp/htdocs/test.php on line 7
我用的是CENT05系统,lampp集成环境,这个集成环境支持Freetds库,连接代码如下:
$msconnect=mssql_connect("SERVER2","sa","aeonsoft");
$msdb=mssql_select_db("Eservice",$msconnect);
$msquery = "select sItemNo,sItemType,sCustName from EG_SHL_ACCEPT";
$msresults= mssql_query($msquery);
//while ($row = mssql_fetch_array($msresults)) {
echo "" . $row['sItemNo'] . " " . $row['sItemType'] . " " . $row['sCustName'] . "\n";
//}
freetds.conf的配置如下:
[SERVER2]
host = 192.168.10.196
client charset =UTF-8
port = 1433
tds version = 8.0
现在不知道问题出在那,请指教,万分感谢。

Posted by: 高山流水 at 2007年07月19日 10:35

你好, 這應該是 php 的 memory_limit 問題
請編輯 php.ini, 將 memory_limit = 8M
調整到 memory_limit = 12M (或更大)
就能解決這個問題

Posted by: Jamyy at 2007年07月19日 11:33

谢谢你的 回复,问题已经解决了 ,正如你 所说的 将php.ini中的 memory_limit=8M的值调大。感谢!

Posted by: 高山流水 at 2007年07月19日 13:51

當我install 完php 嘗試restart 個apache 時就有以下errors:
Starting httpd: Syntax error on line 190 of /etc/httpd/conf/httpd.conf:
Cannot load /usr/lib/httpd/modules/libphp5.so into server: libsybdb.so.5: failed to map segment from shared object: Permission denied

點樣可以解決呢個問題呢?

Posted by: Jason at 2007年07月25日 16:22

應該是 SELinux 所造成, 請參考這篇:
http://www.goodspeed.com.cn/47963.html

Posted by: Jamyy at 2007年07月25日 16:29

你好, 這應該是 php 的 memory_limit 問題
請編輯 php.ini, 將 memory_limit = 8M
調整到 memory_limit = 12M (或更大)
就能解決這個問題

您好 我將參數改成1024M 確依然顯示此錯誤
sql指令僅select top 10 .....
top1的話就可以跑出..
短短10筆資料就把我的2g記憶体佔光光實在有鬼...
還有其它地方可設定嗎..

Posted by: zerohung at 2007年12月20日 18:11

您好..
我還沒加
client charset=cp950
時連的上..但加了client charset=cp950
時會出現Unable to connect to server
我把freetds.log叫出來看..

(write.c:162):tds_put_string wrote 13 bytes
(write.c:134):tds_put_string converting 10 bytes of "DB-Library"
(write.c:162):tds_put_string wrote 10 bytes
(write.c:134):tds_put_string converting 10 bytes of "us_english"
(write.c:162):tds_put_string wrote 10 bytes
(write.c:162):tds_put_string wrote 0 bytes
(token.c:310):tds_process_login_tokens()
(util.c:119):Changing query state from IDLE to DEAD
(token.c:2252):tds_client_msg: #20004: "Read from SQL server failed.". Connection state is now 4.
(token.c:314):looking for login token, got 0()
(token.c:105):tds_process_default_tokens() marker is 0()
(token.c:108):leaving tds_process_default_tokens() connection dead
(util.c:119):Changing query state from DEAD to DEAD
(token.c:2252):tds_client_msg: #20014: "Login incorrect.". Connection state is now 4.
(mem.c:519):tds_free_all_results()
(dblib.c:4978):in dbfreebuf()

Posted by: 小蜂 at 2008年03月03日 13:53

小蜂您好,

不好意思, 由於我這邊的環境沒有出現如您所說的問題, 麻煩請您進行以下測試:

1. 把 cp950 改成 CP950 (大寫)?
2. 把 cp950 改成 UTF-8 (大寫)?

如果可以的話, 請告訴我哪種方式可以排除這個問題, 謝謝 :)

Posted by: Jamyy at 2008年03月03日 16:27

你好! 我用freetds提供的libsybdb编写LINUX程序用于连接SQL SERVER2000, 我需要INSERT插入中文字符,插入返回正确,但显示的是乱码。我试过GB2312和UTF-8编码,均乱码,何解?

Posted by: fay at 2008年05月21日 15:06

我已经解决了。希望对有同样问题的朋友有所帮助
DBSETLCHARSET可以设置编码,然后插入时使用相应的编码就可以

=====================
...
...
...
dbinit();

LOGINREC *loginrec=dblogin();
DBSETLUSER(loginrec, szUsername);
DBSETLPWD(loginrec, szPassword);
DBSETLCHARSET(loginrec, "UTF-8");
DBPROCESS *dbprocess=dbopen(loginrec, szServer);

if(dbprocess==FAIL)
{
...
...
...

Posted by: fay at 2008年05月22日 09:08