请教linux系统中如何通过ODBC访问远端SQL SERVER数据库

发表于:2007-05-26来源:作者:点击数: 标签:
我现在在做 linux 下的odbc数据库编程,需要通过odbc接口访问远端的 SQL SERVER数据库,现在我下载了 unix ODBC-2.2.1.tar为ODBC数据源管理器,freetds作为SQLSERVER的客户端驱动,可是连接出现错误,不知道有没有其他方法可以解决linux下通过odbc数据源访问

我现在在做linux下的odbc数据库编程,需要通过odbc接口访问远端的SQL SERVER数据库,现在我下载unixODBC-2.2.1.tar为ODBC数据源管理器,freetds作为SQL SERVER的客户端驱动,可是连接出现错误,不知道有没有其他方法可以解决linux下通过odbc数据源访问远断SQL SERVER数据库(最好所需软件是免费,因为是自己用*_*),谢谢!

 菜青虫 回复于:2003-11-05 12:03:13
推荐你直接使用freetds来连接,这样比较简单,反正你只是需要访问数据库,并且odbc的程序也是要你自己写的。我当时用freetds来连接sybase数据库,感觉使用起来还是很简单的。

 haricot 回复于:2003-11-05 14:24:51
直接使用FREETDS连接?不太明白,能说详细些么?

 菜青虫 回复于:2003-11-06 00:33:25
[quote:c5d4413fd9="haricot"]直接使用FREETDS连接?不太明白,能说详细些么?[/quote:c5d4413fd9]
freetds本身就能够连接sql server数据库。我用他来查询sybase数据库。由于历史上的原因,sql server的底层其实是MS从sybase公司买来的。所以,freetds既能连接sybase,也能够连接sql server。

我当时其实就是把freetds里面的一个应用程序的代码稍微修改了一下,就能够连接sybase来进行查询了。具体的该文件的位置为freetds-0.61.2/src/apps/tsql.c。你可以编译该文件然后学会如何使用。一般情况下你直接调用
tsql -H host_ip_address -p host_port -U username -P passwd
这里host_ip_address就是你sql server服务器的ip地址,host_port是sql server的端口号,sybase默认是5000,如果我没猜错,sql server应该也是。username和passwd应该不用说了。tsql这个工具有一点问题就是如果passwd为空就无法登录,你可以自己修改代码来解决这个问题。
我想你把这个tsql.c文件好好看看,就应该会知道如何使用freetds的函数库了。比较简单的。如果还有什么问题,可以发mail或者message来问我。

 haricot 回复于:2003-11-06 15:07:47
不知道在使用FREETDS访问远端数据库时,时不时必需在freetds.conf文件中增加一条相关信息

 菜青虫 回复于:2003-11-06 16:36:20
如果直接指定server_ip和port,是不需要配置freetds.conf文件的。我就是直接在代码中指定IP和PORT来访问数据库的。

 菜青虫 回复于:2003-11-06 16:40:03
我对数据库的操作基本上的代码如下,自己感觉写的不好,见笑了。
[code:1:0d67d41244]
#ifndef __SYBASE_H__
#define __SYBASE_H__

class SYDatabase {
public:
SYDatabase(void);
~SYDatabase(void);
public:
int Initial(void);
int Connect(const char *host, int port, const char *username, const char *passwd);
void Disconnect(void);
friend class SYRecordSet;
protected:
void *m_tds;
void *m_login;
void *m_context;
};

#endif /* __SYBASE_H__ */
[/code:1:0d67d41244]

[code:1:0d67d41244]
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <sys/time.h>
#include <time.h>
#include <assert.h>

#include <tds.h>
#include <tdsconvert.h>
#include "sybase.h"

SYDatabase::SYDatabase()
{
m_tds = NULL;
m_login = NULL;
m_context = NULL;
}

SYDatabase::~SYDatabase()
{
Disconnect();
}

int
tsql_handle_message(TDSCONTEXT * context, TDSSOCKET * tds, TDSMSGINFO * msg)
{
if (msg->msg_number == 0) {
fprintf(stderr, "%s\n", msg->message);
return 0;
}

if (msg->msg_number != 5701 && msg->msg_number != 20018) {
fprintf(stderr, "Msg %d, Level %d, State %d, Server %s, Line %d\n%s\n",
msg->msg_number, msg->msg_level, msg->msg_state, msg->server, msg->line_number, msg->message);
}

return 0;
}

int SYDatabase::Initial(void)
{
TDSLOGIN *login = NULL;
TDSCONTEXT *context = NULL;

do {
login = tds_alloc_login();
if (!login)
break;
context = tds_alloc_context();
if (!context)
break;
if (context->locale && !context->locale->date_fmt){
context->locale->date_fmt = strdup("%Y%m%d");
}
context->msg_handler = tsql_handle_message;
context->err_handler = tsql_handle_message;
m_login = (void*)login;
m_context = (void*)context;
return 0;
}while(0);
if (login)
tds_free_login(login);
if (context)
tds_free_context(context);
return -1;
}

int SYDatabase::Connect(const char *host, int port, const char *user, const char *passwd)
{
TDSLOGIN *login = (TDSLOGIN*)m_login;
TDSCONTEXT *context = (TDSCONTEXT*)m_context;
TDSSOCKET *tds = NULL;
TDSCONNECTINFO *connect_info = NULL;
do {
if (!login || !context)
break;
tds_set_user(login,user);
tds_set_app(login,"SYDATABASE_CLASS");
tds_set_library(login,"TDS-Library");
tds_set_server(login,host);
tds_set_port(login,port);
tds_set_charset(login,"roman8");
tds_set_language(login,"us_english");
tds_set_packet(login,512);
tds_set_passwd(login,passwd);
tds = tds_alloc_socket(context,512);
if (!tds)
break;
tds_set_parent(tds,NULL);
connect_info = tds_read_config_info(NULL,login,context->locale);
if (!connect_info || tds_connect(tds, connect_info) == TDS_FAIL)
break;
tds_free_connect(connect_info);
m_tds = (void*)tds;
return 0;
}while(0);
if (connect_info)
tds_free_connect(connect_info);
if (tds)
tds_free_socket(tds);
return -1;
}

void SYDatabase::Disconnect(void)
{
if (m_tds){
tds_free_socket((TDSSOCKET*)m_tds);
m_tds = NULL;
}
if (m_login){
tds_free_login((TDSLOGIN*)m_login);
m_login = NULL;
}
if (m_context){
tds_free_context((TDSCONTEXT*)m_context);
m_context = NULL;
}
}
[/code:1:0d67d41244]

 haricot 回复于:2003-11-06 17:36:12
我现在还是无法连接上远端数据库,情况如下:
# tsql -H 202.112.109.114 -p 5000 -U helitech -P 123456
locale is "zh_CN.GB18030"
charset is "GB18030"
src/tds/login.c: tds_connect: 202.112.109.114:5000: 拒绝连接
Msg 20009, Level 9, State 0, Server OpenClient, Line 0
Server is unavailable or does not exist.
There was a problem connecting to the server

# tsql -S MyServer2000 -p 1433 -U helitech -P 123456
locale is "zh_CN.GB18030"
charset is "GB18030"
There was a problem connecting to the server

不知道是哪里出了问题.

 菜青虫 回复于:2003-11-06 23:04:42
应该是端口不对。你应该在你的sql server服务器上面察看一下侦听端口是多少?
可以用这个指.netstat -na | find "LISTENING"
可以看到服务器上面打开的端口号。对sql server不熟悉,我去看看freetds的主页

 菜青虫 回复于:2003-11-06 23:15:18
我察看了一下freetds的主页,我想你需要去确认两点,第一,ms sql的侦听端口到底是多少?第二,ms sql的Authentication的类型。你需要standard security的认证类型。这种类型使用起来应当相对简单。
具体的内容你可以去察看freetds的FAQ和User Guide。

 haricot 回复于:2003-11-07 11:56:55
我现在通过以下命令可以访问远端DB:
tsql -H 202.112.109.87 -p 1433 -U helitech -P 123456
locale is "zh_CN.GB18030"
charset is "GB18030"
1> select * from billing_record
2> go

但通过这个命令确不行:
 tsql -S MyServer2000 -p 1433 -U helitech -P 123456
locale is "zh_CN.GB18030"
charset is "GB18030"
There was a problem connecting to the server

我觉得freetds.conf文件没有配置错误亚:
# A typical Microsoft SQL Server 2000 configuration
;[MyServer2000]
; host = 202.112.109.87
; port = 1433
; tds version = 7.0


麻烦你了:)

 菜青虫 回复于:2003-11-07 12:07:14
嘿嘿,这个,你最好自己看看他们之间的差别了,我觉得只要有一种方法可以连接就可以了。刚才我试过了,两种配置连接sql 7都能够成功。

 haricot 回复于:2003-11-11 11:40:39
我现在已经解决了以上的问题,谢谢菜青虫的热心帮忙:)
不过我现在在LINUX8.0系统下装FREETDS时,在MAKE时却出现AUTOCONFIG的版本过低这类的错误,可是我在另外一台LINUX9.0系统下安装却没有问题

 vega_ww 回复于:2003-12-03 21:01:48
菜青虫:我现在在做linux下用C编程实现对远端SQL SERVER访问,我看了你给haricot的回复,觉得你很热情,而且很牛。我想请教你:要实现我的这个程序,是不是linux机上只需要安装freetds就可以了?如果是的,那么freetds支持C编程吗?(因为我看到你是用C++写的,不知道可不可以用C写)如果支持,那么在哪里找对应的API呢?如果你会用C写,能不能给我个例程呢?先谢谢你了!

 海里的大青蛙 回复于:2003-12-04 10:37:17
唉,7可以2000为什么就不行??

 菜青虫 回复于:2003-12-04 11:24:11
[quote:1105e38825="vega_ww"]菜青虫:我现在在做linux下用C编程实现对远端SQL SERVER访问,我看了你给haricot的回复,觉得你很热情,而且很牛。我想请教你:要实现我的这个程序,是不是linux机上只需要安装freetds就可以了?如果是的,那么freetd..........[/quote:1105e38825]
其实freetds本身就是用C开发的,并且提供的都是C的接口函数,我只是因为公司内部其他开发员习惯使用了另外一个Oracle的接口函数,所以我就把他们给封装成和那个接口类似的东西,你完全可以直接调用freetds的接口函数。
就象上面我给出的建议一样,其实我觉得tsql这个工具的源代码真的就是一个最足够好的sample了,如果你在阅读和调试他的源代码上有问题,欢迎来找我一起讨论。
理论上只要下载了freetds的数据包就应该可以了,需要注意的是sql2000里面有特殊的要求,特别的是认证方式,最好去freetds的主页好好看看。
祝你好运

 vega_ww 回复于:2003-12-04 11:36:15
菜青虫:谢谢你!我刚才已经在机子上安装了freetds,而且用tsql可以成功连接SQL SERVER  2000,下一步我就要用C程序来实现连接和读写了。谢谢你的建议,我会仔细看看tsql的代码,如果有不懂的还会向你请教。很感谢你的热情!

 vega_ww 回复于:2003-12-05 11:47:12
菜青虫:我昨天看了tsql的源代码,main()的基本框架我已经看懂了,其中用到的readline(),add_history(),populate_login(),tsql_handle_message()我都知道是做什么用的了,但是涉及到查询的
get_opt_flags(),do_query()我都看不大懂,特别是do_query()。我想do_query()是这里面很重要的一个函数。

另外,我对照着main()里的for循环试着输入相应的tsql命令,其中exit,
version,和reset都弄懂了,就是不知道用什么命令来进行查询,我输入:
1>select * from table_1(table_1是SQL SERVER上的mydb数据库里的  
                                       一个表)
2>go
结果显示:Msg 208,Level 16,State 1,Server VEGA-0OITIJGF9B,Line 1
                Invalid object name 'table_1'
应该用什么格式的命令查询呢?SQL SERVER那边是不是要设置系统数据源?

我最后要编写的程序的目的是要获得SQL SERVER里某个数据库里的数据
并保存在本机上,所以查询这一步很重要,我一定要搞清楚才行。麻烦你
了!你能否把你的E-mail告诉我呢?我想尽快联系你,因为这个项目有点
紧,我想第一时间和你联系。

 菜青虫 回复于:2003-12-05 13:10:01
我觉得是因为你登录的用户默认数据库不是mydb,可以在数据库服务器上修改设置,或者在tsql里面用use mydb命令。

 vega_ww 回复于:2003-12-05 13:41:24
菜青虫:我用use mydb后就成功了。谢谢你的帮助。
我的信箱是:517hui@21cn.com,如果你能把你的E-mail或者qq告诉我,就和我联系吧。

 vega_ww 回复于:2003-12-08 15:13:58
菜青虫:我把tsql.c原封不动地保存为另一个文件,编译的时候会出现找不到tds.h和tdsconvert.h文件的错误,而且do_query(),get_opt_flags(),
populate_login()里出现了找不到变量等等一些错误,请问原因是不是系统
找不到*.h和*.so文件的位置?我看了freetds.org上的user guide,用了
$export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/freetds/lib
# echo /usr/local/freetds >> /etc/ld.so.conf
# ldconfig
命令,可是没用。我应该怎么办?

 明清风 回复于:2004-01-05 19:00:24
你好,不好意思!
我在freebsd系统上装这个freetds,要连接sql server2000搞了好几天了.郁闷!
web# /usr/local/freetds/bin/tsql -S WUMX -p 1433 -U sa -P 123456
locale is "C"
charset is "US-ASCII"
There was a problem connecting to the server
web# /usr/local/freetds/bin/tsql -H 192.168.1.17 -p 1433 -U sa -P 123456
locale is "C"
charset is "US-ASCII"
src/tds/login.c: tds_connect: 192.168.1.17:1433: Connection refused
Msg 20009, Level 9, State 0, Server OpenClient, Line 0
Server is unavailable or does not exist.
There was a problem connecting to the server
不知怎么,就是不行.我不懂编程.所以看freetds主页时,理解有一定限制.请你帮我具体分析一下好吗?我的QQ是:15955666.我白天都会在线.谢谢了!

 blackstarreddiamond 回复于:2004-03-18 08:54:44
你的连接函数中CONNECT中为什么要释放SOCK啊,那不是连接就断开了

 明清风 回复于:2004-03-18 09:48:06
我已经搞定.谢谢!

 blackstarreddiamond 回复于:2004-03-18 18:08:00
有没有一个函数或是方法可以插入记录到远程SQL server服务端,如何做啊,我看了一下tsql 好象它不能做到这点,不知用freetds的什么函数才能做到啊!如果那位大侠知道还望告知。

 blackstarreddiamond 回复于:2004-03-19 10:51:58
可 不可以在tsql 中打入insert into 语句啊!
为什么我的数据库老是说无效的表名呢!我也用了use mydb可是还是有问题有人可以帮忙马

 blackstarreddiamond 回复于:2004-03-19 16:51:38
多谢菜青虫的文档,对于一个初级人员来说你们的帮助是那么的重要,这年头过生活真不容易,不知如何在tsql中输入中文啊!对了还得问一下tsql 支持中文吗?谢谢!忘了说一声insert into的问题我已解决了!tsql.c真是个不错的好东

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)