远程访问数据库问题

nkwesley 2003-11-25 07:43:32
关于数据库的远程访问。比如说,局域网内有一台服务器,在这台服务器上有一个独立的数据库,在该局域网内的其他机器希望能远程访问服务器上的数据库。如果用SQL Server等商业软件,开发成本抬高。假如用文件共享的方式来实现,似乎不是很好,因为同步操作比较复杂,可能会出现数据读写的不一致,产生垃圾数据,而且用通讯命令来携带大量的数据不是很方便。我想知道,如何能比较方便的实现对远程数据库的访问,好象ADO是可以实现的,但是我对ADO不是很了解,也不知道可靠性是否能保证,希望大侠提供帮助。




...全文
122 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
illocal 2003-12-03
  • 打赏
  • 举报
回复
一台主机做sql server服务器,开启服务面向全网,其他机器做得只是有驱动支持数据连接,然后建立数据连接对象比如connectionand recordset类型来对数据库操作,至于同步性于可靠性,这是连接驱动和sqlserver内部机制的问题,做得时候不需要考虑吧。
如果是网络型数据库,像sql或oracle,这时要保证同时读写一致有两种方式:一是某一
方修改完数据提交到数据库时先考察数据是否是自己修改前的数据,是的话再修改;另一种是用锁的机制。但是这两种方法仍有可能出现问题,例如死锁,或是俩个人同时去锁,都以为成功了,但最后肯定是有一方操作失败了。所以这个问题要在应用时(也就是程序中)解决,例如可以利用事务处理,对表写一个存储过程,使某些操作有数据库服务器自动完成,以保证并发性和可靠性。
还有,ADO是一个高层的数据模型,是一个调用接口,在应用上一般使用它的底层,例如OLEdb等,它不涉及并发性的问题。
ivy_live521 2003-11-25
  • 打赏
  • 举报
回复
楼主是不是只是想实现局域网内共享文件的即时更新??
youngby 2003-11-25
  • 打赏
  • 举报
回复
up

mark
pengdali 2003-11-25
  • 打赏
  • 举报
回复
以VC举例:

1.配置ODBC,建立ODBC和SQL SERVER的连接ODBCTEST
2.在VC++通过该ODBC调用SQL SERVER的STORED PROCEDURE(szTypes )
#include "stdafx.h"
#include "DatabaseServer.h"
#include <stdarg.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDatabaseServer::CDatabaseServer()
{

}

CDatabaseServer::~CDatabaseServer()
{

}

bool CDatabaseServer::getConnectionString(char *szConnectionString)
{
char szServerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwSize=sizeof(szServerName) ;
if(!GetComputerName(szServerName,&dwSize))
return false ;


if(!szConnectionString)
return false ;

char szUserName[] = "SA";
char szPassword[] = "";
char szDatabase[] = "IPLOMA";//ADD YOU DATEBASE NAME

sprintf(szConnectionString,"DSN=ODBCTEST;uid=%s;pwd=%s;",szServerName,szDatabase,szUserName,szPassword); //建立CONNECTION STRING

return true;
}

VARIANT CDatabaseServer::getExecStoredProcedure(char *szTypes,SAFEARRAY *pSPFields)
{
_variant_t vtResultRows;
try
{
_CommandPtr pCmdPtr;
_RecordsetPtr pRecordset;
HRESULT hr ;

hr = pCmdPtr.CreateInstance(__uuidof(Command));

char szConnectionString[255];
getConnectionString(szConnectionString);
_variant_t vtConnectionString(szConnectionString);
pCmdPtr->put_ActiveConnection(vtConnectionString);

pCmdPtr->CommandType = adCmdStoredProc; //CALL SQL SP
pCmdPtr->CommandText = szTypes ; //YOU SP NAME
hr = pCmdPtr->Parameters->Refresh();

long lBound,uBound ;
HRESULT hresult ;
// Getting Safe Array's Lower and Upper Bounds
hresult = SafeArrayGetLBound(pSPFields, 1, &lBound);
hresult = SafeArrayGetUBound(pSPFields, 1, &uBound);

variant_t vtParamVal;
_variant_t Index;
Index.vt = VT_I2;
Index.iVal = 1 ;
for (long iElements=lBound;iElements<=uBound;iElements++)
{
hresult = SafeArrayGetElement(pSPFields, &iElements, &vtParamVal);
pCmdPtr->GetParameters()->GetItem(Index)->PutValue(vtParamVal) ;
Index.iVal++ ;
}

//Execute current Stored Procedure
_variant_t vEffected ;
pRecordset = pCmdPtr->Execute(&vEffected,NULL,NULL);
if (pRecordset->BOF || pRecordset->EndOfFile)
throw ;
// Get result set in the form of array
vtResultRows = pRecordset->GetRows(-1);
return vtResultRows.Detach() ;
}
catch(_com_error &e)
{
ATLTRACE((LPCSTR)e.Description());
}
vtResultRows.vt = VT_EMPTY ;
return vtResultRows.Detach();
}

long CDatabaseServer::setExecStoredProcedure(char *szTypes,SAFEARRAY *pSPFields)
{
_variant_t vtResultRows;
try
{
_CommandPtr pCmdPtr;
_RecordsetPtr pRecordset;
HRESULT hr ;

hr = pCmdPtr.CreateInstance(__uuidof(Command));

char szConnectionString[255];
getConnectionString(szConnectionString);
_variant_t vtConnectionString(szConnectionString);
pCmdPtr->put_ActiveConnection(vtConnectionString);

pCmdPtr->CommandType = adCmdStoredProc;
pCmdPtr->CommandText = szTypes ;
hr = pCmdPtr->Parameters->Refresh();

long lBound,uBound;
HRESULT hresult;
// Getting Safe Array's Lower and Upper Bounds
hresult = SafeArrayGetLBound(pSPFields, 1, &lBound);
hresult = SafeArrayGetUBound(pSPFields, 1, &uBound);

variant_t vtParamVal;
_variant_t Index;
Index.vt = VT_I2;
Index.iVal = 1 ;
for (long iElements=lBound;iElements<=uBound;iElements++)
{
hresult = SafeArrayGetElement(pSPFields, &iElements, &vtParamVal);
pCmdPtr->GetParameters()->GetItem(Index)->PutValue(vtParamVal) ;
Index.iVal++ ;
}

_variant_t vEffected ;
pCmdPtr->Execute(&vEffected,NULL,NULL);

// We Are Expecting That Stored Procedures Return ID for Entity to which
// NSERT/UPDATE/DELETE operation is being performed
return (long)pCmdPtr->Parameters->Item["RETURN_VALUE"]->Value ;
}
catch(_com_error &e)
{
ATLTRACE((LPCSTR)e.Description());
}
return 0;
}
蓝天 2003-11-25
  • 打赏
  • 举报
回复
mysql不是免费的吗?可以考虑哦

txlicenhe 2003-11-25
  • 打赏
  • 举报
回复
我倒觉得语言并不是最重要的,楼主的目的倒是第一位的。
蓝天 2003-11-25
  • 打赏
  • 举报
回复
如果不用商用数据库,最简单的方法就是加锁。

其实就是把并行的东西串行化。否则必须考虑并发(商用数据库都能处理并发)。这个并发不是很好解决的,你可以找数据库的相关书籍看看。

txlicenhe 2003-11-25
  • 打赏
  • 举报
回复
不知道楼主想要干什么?
你是怎样的数据库? 是为开发系统做的数据库还是为了局域网内的文件共享之类啊?

pengdali 2003-11-25
  • 打赏
  • 举报
回复
你说了半天,没说你用什么语言。
pengdali 2003-11-25
  • 打赏
  • 举报
回复
select * into 本地库名..表名 from OPENDATASOURCE(
'SQLOLEDB',
'Data Source=远程ip;User ID=sa;Password=密码'
).库名.dbo.表名

insert 本地库名..表名 select * from OPENDATASOURCE(
'SQLOLEDB',
'Data Source=远程ip;User ID=sa;Password=密码'
).库名.dbo.表名

或使用联结服务器:
EXEC sp_addlinkedserver '别名','','MSDASQL',NULL,NULL,'DRIVER={SQL Server};SERVER=远程名;UID=用户;PWD=密码;'
exec sp_addlinkedsrvlogin @rmtsrvname='别名',@useself='false',@locallogin='sa',@rmtuser='sa',@rmtpassword='密码'
GO
然后你就可以如下:
select * from 别名.库名.dbo.表名
insert 库名.dbo.表名 select * from 别名.库名.dbo.表名
select * into 库名.dbo.新表名 from 别名.库名.dbo.表名
go

34,874

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧