SQL:自定义记录集的 SQL 语句 (ODBC)
本主题介绍:
框架如何构造 SQL 语句
如何重写 SQL 语句
注意
此信息适用于 MFC ODBC 类。 如果使用的是 MFC DAO 类,请参阅 DAO 帮助中的主题“Microsoft Jet 数据库引擎 SQL 和 ANSI SQL 的比较”。
SQL 语句构造
记录集的记录选择主要基于 SQL SELECT 语句。 使用向导声明类时,它会写入一个重写版本的 GetDefaultSQL
成员函数,其外观如下所示(针对名为 CAuthors
的记录集类)。
CString CAuthors::GetDefaultSQL()
{
return "AUTHORS";
}
默认情况下,此重写返回使用向导指定的表名称。 在此示例中,表名称为“AUTHORS”。稍后调用记录集的 Open
成员函数时,Open
会构造最终的 SELECT 语句,其格式如下:
SELECT rfx-field-list FROM table-name [WHERE m_strFilter]
[ORDER BY m_strSort]
其中,通过调用 GetDefaultSQL
获取 table-name
,并从 DoFieldExchange
中的 RFX 函数调用获取 rfx-field-list
。 这是 SELECT 语句的结果,除非在运行时将其替换为重写版本,不过也可以使用参数或筛选器修改默认语句。
注意
如果指定包含(或可能包含)空格的列名称,则必须将名称括在方括号中。 例如,名称“First Name”应为“[First Name]”。
若要重写默认 SELECT 语句,请在调用 Open
时传递包含完整 SELECT 语句的字符串。 记录集使用所提供的字符串,而不是构造自己的默认字符串。 如果替换语句包含 WHERE 子句,请不要在 m_strFilter
中指定筛选器,因为这样做之后会有两个 filter 语句。 同样,如果替换语句包含 ORDER BY 子句,请不要在 m_strSort
中指定排序,这样就不会有两个 sort 语句。
注意
如果在筛选器中使用文字字符串(或 SQL 语句的其他部分),则必须使用特定于 DBMS 的文字前缀和文字后缀字符将这些字符串“引起来”(括在指定分隔符中)。
对于外部联接等操作,可能还会遇到特殊语法要求,具体取决于 DBMS。 使用 ODBC 函数从 DBMS 驱动程序获取此信息。 例如,针对 SQL_VARCHAR
等特定数据类型调用 ::SQLGetTypeInfo
以请求 LITERAL_PREFIX 和 LITERAL_SUFFIX 字符。 如果要编写与数据库无关的代码,请参阅 ODBC 程序员参考中的附录 C:SQL 语法以获取详细的语法信息。
除非你传递自定义 SQL 语句,否则记录集对象会构造用于选择记录的 SQL 语句。 完成此操作的方式主要取决于在 Open
成员函数的 lpszSQL 参数中传递的值。
SQL SELECT 语句的一般格式为:
SELECT [ALL | DISTINCT] column-list FROM table-list
[WHERE search-condition][ORDER BY column-list [ASC | DESC]]
将 DISTINCT 关键字添加到记录集的 SQL 语句的一种方法是将此关键字嵌入到 DoFieldExchange
中的第一个 RFX 函数调用中。 例如:
...
RFX_Text(pFX, "DISTINCT CourseID", m_strCourseID);
...
注意
仅对打开为只读的记录集使用此方法。
重写 SQL 语句
下表显示了 lpszSQL 参数为 Open
的各种可能性。 表后对表中的各案例进行了解释。
lpszSQL 参数及生成的 SQL 字符串
案例 | 传入 lpszSQL 的内容 | 生成的 SELECT 语句 |
---|---|---|
1 | Null | SELECT rfx-field-list FROM table-nameCRecordset::Open 调用 GetDefaultSQL 获取表名称。 生成的字符串是案例 2 到 5 中的一个,具体取决于 GetDefaultSQL 返回的内容。 |
2 | 表名称 | SELECT rfx-field-list FROM table-name 字段列表取自 DoFieldExchange 中的 RFX 语句。 如果 m_strFilter 和 m_strSort 不为空,则添加 WHERE 和/或 ORDER BY 子句。 |
3 * | 完整的 SELECT 语句,但没有 WHERE 或 ORDER BY 子句 | 如所传递内容。 如果 m_strFilter 和 m_strSort 不为空,则添加 WHERE 和/或 ORDER BY 子句。 |
4 * | 完整的 SELECT 语句,且包含 WHERE 和/或 ORDER BY 子句 | 如所传递内容。 m_strFilter 和/或 m_strSort 必须保持为空,否则将生成两个 filter 和/或 sort 语句。 |
5 * | 对存储过程的调用 | 如所传递内容。 |
* m_nFields
必须小于或等于 SELECT 语句中指定的列数。 SELECT 语句中指定的每列的数据类型必须与相应 RFX 输出列的数据类型相同。
案例 1 lpszSQL 为 NULL
记录集选择取决于 CRecordset::Open
调用 GetDefaultSQL
时返回的内容。 案例 2 到 5 介绍了可能的字符串。
案例 2 lpszSQL 为表名称
记录集使用记录字段交换 (RFX) 根据记录集类 DoFieldExchange
重写中的 RFX 函数调用提供的列名称生成列列表。 如果使用了向导来声明记录集类,则此案例的结果与案例 1 相同(前提是传递向导中指定的同一表名称)。 如果不使用向导编写类,则案例 2 是构造 SQL 语句的最简单方法。
以下示例将构造一个从 MFC 数据库应用程序选择记录的 SQL 语句。 当框架调用 GetDefaultSQL
成员函数时,该函数返回表的名称 SECTION
。
CString CEnrollSet::GetDefaultSQL()
{
return "SECTION";
}
若要为 SQL SELECT 语句获取列的名称,框架将调用 DoFieldExchange
成员函数。
void CEnrollSet::DoFieldExchange(CFieldExchange* pFX)
{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, "CourseID", m_strCourseID);
RFX_Text(pFX, "InstructorID", m_strInstructorID);
RFX_Text(pFX, "RoomNo", m_strRoomNo);
RFX_Text(pFX, "Schedule", m_strSchedule);
RFX_Text(pFX, "SectionNo", m_strSectionNo);
}
完成后,SQL 语句如下所示:
SELECT CourseID, InstructorID, RoomNo, Schedule, SectionNo
FROM SECTION
案例 3 lpszSQL 为 SELECT/FROM 语句
手动指定列列表,而不是依赖于 RFX 进行自动构造。 在以下情况下可能需要执行此操作:
要指定 SELECT 后面的 DISTINCT 关键字时。
列列表应与
DoFieldExchange
中所列的列名称和类型的顺序一致。有理由使用 ODBC 函数
::SQLGetData
手动检索列值而不依赖 RFX 来绑定和检索列时。例如,可能需要容纳分发应用程序后应用程序客户向数据库表添加的新列。 需要添加这些额外的字段数据成员,而这些成员在你使用向导声明类时是未知的。
列列表应与
DoFieldExchange
中所列的列名称和类型的顺序一致,后跟手动绑定列的名称。 有关详细信息,请参阅记录集:动态绑定数据列 (ODBC)。要通过在 FROM 子句中指定多个表来联接表时。
有关信息和示例,请参阅数据集:执行联接 (ODBC)。
案例 4 lpszSQL 为带 WHERE 和/或 ORDER BY 的 SELECT/FROM
指定所有内容:列列表(基于 DoFieldExchange
中的 RFX 调用)、表列表以及 WHERE 和/或 ORDER BY 子句的内容。 如果以这种方式指定 WHERE 和/或 ORDER BY 子句,请不要使用 m_strFilter
和/或 m_strSort
。
案例 5 lpszSQL 为存储过程调用
如果需要调用预定义查询(例如 Microsoft SQL Server 数据库中的存储过程),则必须在传递给 lpszSQL 的字符串中写入 CALL 语句。 向导不支持声明用于调用预定义查询的记录集类。 并非所有预定义查询都返回记录。
如果预定义查询未返回记录,可以直接使用 CDatabase
成员函数 ExecuteSQL
。 对于返回记录的预定义查询,还必须为过程返回的任何列在 DoFieldExchange
中手动写入 RFX 调用。 RFX 调用必须与预定义查询具有相同的顺序,并且返回相同的类型。 有关详细信息,请参阅记录集:为预定义查询声明一个类 (ODBC)。