我刚学数据库编程 按照书上说的步骤一步步操作:在SOL2000建立的个数据库,然后在控制面板里面连接了ODBC数据源,然后在VC用AppWizard 建立了项目,并在创建过程中选定了数据库和表,建立好后,添加了一个按钮控件,控件中代码:
CabcSet sam;
sam.Open (CRecordset::dynaset,"abc");
m_pSet->AddNew ();
m_pSet->m_name ="fd";
m_pSet->Update ();
但运行后 出错说数据集是只读的! 这个是为什么啊? 到底怎么才可以在数据库中添加数据啊!
求教!
CabcSet sam;
sam.Open (CRecordset::dynaset,"abc");
m_pSet->AddNew ();
m_pSet->m_name ="fd";
m_pSet->Update ();
但运行后 出错说数据集是只读的! 这个是为什么啊? 到底怎么才可以在数据库中添加数据啊!
求教!
解决方案 »
- 如何改变程序所有对话框背景颜色
- 在 IE 的 url 地址栏中输入网址时候,一般都会自动弹出一个下拉的提示栏,这个提示栏是怎么出来的?
- 【求助】怎么遍历目前所有的窗口,并且打印所有窗口的名称,类似Spy++那样?
- 请问怎么样在代码中控制让COMBOBOX下拉框弹出来?
- 我用重叠I/O模型写的一个CNet类,已用在商业项目中,欢迎批评指正!!散分
- installshield 有关把mfc的动态库安装到系统目录下的问题?
- 我怎么的得到视图的指针?
- 使用 VTooolsD 出错如下,是不是路径设置不对,请大侠帮我!
- 如何让我的程序拥有更高的权限???
- 如何在程序运行中,使CToolBar 中的某个Button不可见,即刻给分
- 请问如何实现数据的导出?
- select的问题?
------------------------------------------------------------------------------------------------------------------------------
CDatabase db;
db.OpenEx (_T"DSN=strtab");
CRecordset m_Set (&db);
m_Set.Open (AFX_DB_USE_DEFAULT_TYPE, _T"select *from strtab");
if (!m_Set.IsOpen ()) AfxMessageBox ("数据集没能打开!");
m_Set.Edit ();
--------------------------------------------------------------------------------------------------------------------------------
检查一下自己的程序,发现不管是声明的CDatabase对像还是通过CRecordset对像打开的记录集都使用的是缺省参数,而在我的记忆中CDatabase::OpenEx()和CRecordset::Open()这两个成员函数的缺省参数打开的记录集和数据库对像都是非只读的。倒底是那里的问题呢?
BOOL CDatabase::OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions)
virtual BOOL Open(UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE,
LPCTSTR lpszSQL = NULL, DWORD dwOptions = none);
我在我的程序中打开数据集的Open()处下了断点并跟踪进去,发现CRecordset对像的m_bUpdatable标志位最初始一直是为TRUE,即可更新状态。随后进入了如下一串令人眼花缭乱的函数调用里,终于找到m_bUpdatable的值在那里被更改,这一切的问题出自那里!
-----------------------------------------------------------------------------------------------------------------------------------------------
BuildSQL(lpszSQL);
if ((m_bUpdatable || m_bAppendable) && !IsRecordsetUpdatable())
if (!IsSQLUpdatable(m_strSQL))
return IsSelectQueryUpdatable(lpszSQL);
lpchTokenFrom = FindSQLToken(strSQL, _afxFrom); //AFX_STATIC_DATA const TCHAR _afxFrom[] = _T(" FROM ");
lpszFoundToken = _tcsstr(lpszFoundToken + nTokenOffset, lpszSQLToken);
--------------------------------------------------------------------------------------------------------------------------------------------------
上面这每一行是跟踪进去的函数,蓝色字是函数名。这些函数是分析传递进来的SQL语句的并进行相应的设置来打开数据集。注意第五行_afxFrom的值是什么!这是MFC定义的一个常量,它的订义在注释那里。问题就在这里了,MFC定义这个常量用来分析SQL语句中是否包含用FROM关键字以及其后的表名,要有这个关键字那么数据集才是以可更新的状态打开的。但是,很明显我的程序中打开数据集用的SQL语句是有这个FROM关键字和表名的。那么我应该得到一个可更新的数据集才对啊,为什么我不能更新呢?仔细看看MFC定义的这个_afxFrom常量,它的值是_T(" FROM ")FROM的前后各有一个空格,因此真相大白了。问题就是我的SQL语句因为要返回所有的字段,就没有给出字段名而是直接用*号表示要返回所有字段,而这个*号紧挨着FROM关键字,所以在最后一行中MFC用_tcsstr()函数在SQL语句中查找_afxFrom,结果是永远也找不到MFC定义的这个两头各有一个空格的FROM关键。_tcsstr()返回一个空指针,接着这些函数一路返回FALSE,这样m_bUpdatable的值就为FALSE,我所打开的数据集也是不可更新数据集。
这样的问题为什么以前没有出现呢?那是因为以前我要不是只返回特定的字段,构造好的SQL语句中的FROM也是同样前后都有空格。就是直接CRecordset::Open()一个参数不带的执行这个Open()函数。这样由MFC自行构造的缺省SQL语句肯定是符合他自己的要求。
实际上,我这样的*号紧挨FROM的SQL语句写法也是很多人的习惯。所以,我相信也有不少的朋友也碰到这样的问题。
另外,SQL语句中有Group by子句或者是多表查询打开的记录集也不能更新和删除。但是MFC又没有具体的错误报告,也是跟踪进去才发现的。还好有源代码,不然不知道伤脑筋成什么样呢。
相关网址:http://blog.csdn.net/ghgk/archive/2004/10/23/147951.aspx
执行下面的代码:
m_db.Open(_T("source_name"));
m_db.ExecuteSQL("insert into abc(name) values('fd')");m_db是CDatabase对象;