4、SQL查询
记录集的建立实际上是一个查询过程,SQL的SELECT语句用来查询数据源。在建立记录集时,CRecordset会根据一些参数构造一个SELECT语句来查询数据源,并用查询的结果创建记录集。SELECT语句的句法如下:
SELECT rfx-field-list FROM table-name [WHERE m_strFilter][ORDER BY m_strSort]
其中table-name是表名,rfx-field-list是选择的列(字段),WHERE和ORDER BY是两个子句,分别用来过滤和排序。举例如下:
(1)SELECT CourseID, InstructorID FROM Section
从Section表中选择CourseID和InstructorID字段。
(2)SELECT * FROM Section WHERE CourseID=‘MATH202’ AND Capacity=15
从Section表中选择CourseID为MATH202且Capacity等于15的记录。该语句中使用了像AND或OR这样的逻辑连接符。
(3)SELECT InstructorID FROM Section ORDER BY CourseID ASC
从Section表中选择InstructorID列并且按CourseID的升序排列,若要降序排列,可使用关键字DESC。
注意:
(1)在SQL语句中引用字符串、日期或时间等类型的数据时要用单引号括起来,而数值型数据则不用。
(2)如果列名或表名中包含有空格,则必须用方括号把该名称包起来。例如,如果有一列名为“Client Name”,则应该写成“[Client Name]”。
5、记录集的建立和关闭
要建立记录集,首先要构造一个CRecordset派生类对象,然后调用Open成员函数查询数据源中的记录并建立记录集。在Open函数中,可能会调用GetDefaultConnect和GetDefaultSQL函数。函数的声明为:
CRecordset(CDatabase* pDatabase=NULL);
参数pDatabase指向一个CDatabase对象,用来获取数据源。如果pDatabase为NULL,则会在Open函数中自动构建一个CDatabase对象。如果CDatabase对象还未与数据源连接,那么在Open函数中会建立连接,连接字符串由成员函数GetDefaultConnect提供。
virtual CString GetDefaultConnect( );
该函数返回缺省的连接字符串。Open函数在必要的时侯会调用该函数获取连接字符串以建立与数据源的连接。一般需要在CRecordset派生类中覆盖该函数并在新版的函数中提供连接字符串。
virtual BOOL Open( UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE, LPCTSTR lpszSQL = NULL, DWORD dwOptions = none ); throw( CDBException, CMemoryException );
该函数使用指定的SQL语句查询数据源中的记录并按指定的类型和选项建立记录集。参数说明如下:
(1)nOpenType
记录集的类型。如果要求的类型驱动程序不支持,则函数将产生一个异常。
类型 |
含义 |
AFX_DB_USE_DEFAULT_TYPE |
使用缺省值。 |
CRecordset::dynaset |
可双向滚动的动态集。 |
CRecordset::snapshot |
可双向滚动的快照。 |
CRecordset::dynamic |
提供比动态集更好的动态特性,大部分ODBC驱动程序不支持这种记录集。 |
CRecordset::forwardOnly |
只能前向滚动的只读记录集。 |
(2)lpszSQL
一个SQL的SELECT语句,或是一个表名。函数用lpszSQL来进行查询,如果该参数为NULL,则函数会调用GetDefaultSQL获取缺省的SQL语句。
virtual CString GetDefaultSQL( );
下面举几个返回字符串的例子:
“Section” //选择Section表中的所有记录到记录集中 “Section, Course” //合并Section表和Course表的各列到记录集中 //对Section表中的所有记录按CourseID的升序进行排序,然后建立记录集 “SELECT * FROM Section ORDER BY CourseID ASC”
(3)dwOptions
一些选项的组合。
选项 |
含义 |
CRecordset::none |
无选项(缺省)。 |
CRecordset::appendOnly |
不允许修改和删除记录,但可以添加记录。 |
CRecordset::readOnly |
记录集是只读的。 |
CRecordset::skipDeletedRecords |
有些数据库(如FoxPro)在删除记录时并不真删除,而是做个删除标记,在滚动时将跳过这些被删除的记录。 |
注意:如果在调用Open时只提供了表名,那么SELECT语句还缺少选择列参数rfx-field-list。框架规定,如果只提供了表名,则选择列的信息从DoFieldExchange中的RFX语句里提取。例如:如果在调用Open时只提供了“Section”表名,那么将会构造如下一个SELECT语句:
SELECT CourseID,SectionNo,InstructorID,RoomNo,Schedule,Capacity FROM Section
6、m_strFilter与m_strSort
建立记录集后,用户可以随时调用Requery成员函数来重新查询和建立记录集。Requery有两个重要用途:
(1)使记录集能反映用户对数据源的改变。
(2)按照新的过滤或排序方法查询记录并重新建立记录集。
在调用Requery之前,可调用CanRestart来判断记录集是否支持Requery操作。要记住Requery只能在成功调用Open后调用,所以程序应调用IsOpen来判断记录集是否已建立。
virtual BOOL Requery( ); throw( CDBException,CMemoryException );
BOOL CanRestart( ) const; //若支持Requery则返回TRUE
CRecordset类有两个公共数据成员m_strFilter和m_strSort用来设置对记录的过滤和排序。在调用Open或Requery前,如果在这两个数据成员中指定了过滤或排序,那么Open和Requery将按这两个数据成员指定的过滤和排序来查询数据源。
(1)m_strFilter
用于指定过滤器。m_strFilter实际上包含了SQL的WHERE子句的内容,但它不含WHERE关键字。例如:
m_pSet->m_strFilter=“CourseID=‘MATH101’”; //只选择CourseID为MATH101的记录
(2)m_strSort
用于指定排序。m_strSort实际上包含了ORDER BY子句的内容,但它不含ORDER BY关键字。例如:
m_pSet->m_strSort=“CourseID DESC”; //按CourseID的降序排列记录
Open函数在构造SELECT语句时,会把m_strFilter和m_strSort的内容放入SELECT语句的WHERE和ORDER BY子句中。如果在Open的lpszSQL参数中已包括了WHERE和ORDER BY子句,那么m_strFilter和m_strSort必需为空。
调用无参数成员函数Close可以关闭记录集。在调用了Close函数后,程序可以再次调用Open建立新的记录集。CRecordset的析构函数会调用Close函数,所以当删除CRecordset对象时记录集也随之关闭。