手机微网站建设案例及报告,营销型网站维护费用,wordpress 调试很慢,网站关键词代码怎么做继续我们的学习,在这一章#xff0c;我们来看看如何通过ODBC来操作数据源.在上一章,我们已学习了第一步#xff0c;怎样连接一个数据源。一个连接定义了用户与数据源的数据通道.它是静态的.如果要想操作数据源#xff0c;我们就必须使用语句(statement).可以认为语句就是发给…继续我们的学习,在这一章我们来看看如何通过ODBC来操作数据源.在上一章,我们已学习了第一步怎样连接一个数据源。一个连接定义了用户与数据源的数据通道.它是静态的.如果要想操作数据源我们就必须使用语句(statement).可以认为语句就是发给数据源的命令.这个命令必须用SQL写成.通过使用语句,我们就可以修改数据源的结构、在其中执行查询、修改及删除数据.准备及使用语句可分为以下几个步骤:分配一个语句句柄(statement handle)创建SQL语句执行语句销毁语句分配一个语句句柄可以通过调用函数 SQLAllocHandle来分配一个语句句柄。例子如下.data?hStmt dd ?.code......invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt创建SQL语句这部分你就得靠自己了你必须知道SQL的语法.比如说,当你想创建一个表时你就得知道CREATE TABLE语句.执行语句执行语句有四种方法,由它们是否被数据库引擎编译过准备好及被怎样定义有关.直接执行(Direct Execution)由用户程序定义SQL语句.语句在运行时(runtime)被编译并执行.编译执行(Prepared Execution)也是由用户程序定义SQL语句但编译和执行被分为两步首先SQL被准备好(被编译)接下来被执行.通过这种方法,我们可以只编译SQL语句一次但执行相同的语句多次以节省时间.存储过程(Procedures)SQL语句被编译并存放在数据源内用户程序可以在运行时调用这些语句.目录(Catalog)SQL被硬编码(hardcoded)在ODBC驱动程序内. 目录函数的目的是返回预定义的结果集例如数据库中的所有表名. 总的来说,目录函数用来获得数据源的信息的用户程序可以在运行时调用它们.这四种方法各有优缺点.当你只运行某一SQL语句一次时直接执行是一个很好的选择如果你要经常运行某一语句,则应首选编译执行因为SQL语句仅在第一次运行时被编译在接下来的运行中它将运行更快因为已被编译过了存储过程是注重速度的最佳选择因为它已被编译过并存放在数据源中了。缺点是并不是所有的数据存储都支持存储过程.目录主要是是用来获得数据源结构的一些信息。在本章中,我们主要看一下直接执行和编译执行因为它们是由我们的程序来完成的.编写存储过程是DBMS(数据库管理系统)的事.而目录将在稍后讨论.直接执行要直接并快速执行SQL语句,以如下语法调用函数SQLExecDirect:SQLExecDirect proto StatementHandle:DWORD,pStatementText:DWORD,TextLength:DWORDStatementHandle. 要使用的语句句柄pStatementText. 指向要执行的SQL语句的指针TextLength. SQL语句的长度.可能的返回值如下:SQL_SUCCESS操作顺利SQL_SUCCESS_WITH_INFO操作顺利但可能产生非致命错误SQL_ERROR操作失败SQL_INVALID_HANDLE使用的语句句柄非法SQL_NEED_DATA如果在执行SQL语句前没有提供足够的参数将会获得这个返回值.这时需调用SQLParamData 或 SQLPutData函数来提交参数.SQL_NO_DATA如果SQL语句不返回结果集例如只是一个查询动作,将获得这个返回值。使用户知道动作成功但没有结果集被返回。SQL_STILL_EXECUTING如果异步执行SQL语句, SQLExecDirect 会立刻返回这个值,表明语句正在执行。在通常情况下如果你使用的一个多线程操作系统异步执行是一个好主意。如果你希望异步执行,旧可以通过SQLSetStmtAttr来设置语句属性。例子:.dataSQLStmt db select * from Sales,0.data?hStmt dd ?.code.....invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt.if axSQL_SUCCESS || axSQL_SUCCESS_WITH_INFOinvoke SQLExecDirect, hStmt, addr SQLStmt, sizeof SQLStmt编译执行SQL的执行被分为两步第一步必须通过调用函数SQLPrepare来*准备*语句。第二步,通过调用SQLExecute函数来执行语句.在使用编译执行时,我们可以多次调用SQLExecute来执行同一语句. 结合使用SQL参数,这个方法对执行同一语句极为有效。SQLPrepare 与SQLExecDirect使用相同的三个参数所以这里不再写出函数原型。 SQLExecute 语法:SQLExecute proto StatementHandle:DWORD只须这一个参数,我想不再需要解释了;)例子:.dataSQLStmt db select * from Sales,0.data?hStmt dd ?.code.....invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt.if axSQL_SUCCESS || axSQL_SUCCESS_WITH_INFOinvoke SQLPrepare, hStmt, addr SQLStmt, sizeof SQLStmtinvoke SQLExecute, hStmt你也许会想编译执行没什么强于直接执行的。上面的例子还不明显。我们需要知道SQL语句的参数来仔细研究它。语句参数(Statement Parameters)这里的参数是指由SQL语句使用的变量.比如说我们有一个叫做 employee的表它有三个字段name, surname和 TelephoneNo 。现在我们要找一个叫做Bob的职员的电话号码, 就可以使用以下SQL语句select telephoneNo from employee where nameBob这条SQL语句象我们希望的那样工作了。但是如果我们又想找另一个职员的电话号码怎么办如果不使用参数,那只好再写一条SQL语句然后再一次编译、执行它。现在我们不会允许这种低效率的行为了。我们可以使用参数来实现目标。在上面的例子中我们必须将字符串/值替换为 ? (被称为参数标志符(parameter marker)).SQL 语句将变成这样:select telephoneNo from employee where name?现在想一下这个问题:ODBC驱动程序如何知道用什么值来替换参数标志符??答案是: 我们必须提供需要的值.这种方法被称为参数绑定(parameter binding).简单点说,就是将一个参数标志符与用户程序中的变量建立连接的过程.在上面的例子中,我们需要创建一个缓冲区来告诉ODBC驱动程序当它需要一个参数的具体值时将从我们提供的字符串缓冲区中获得。一旦一个参数与一个变量绑定,它将一直保持绑定直到被绑定到另一变量或直到所有参数都被函数 SQLFreeStmt以(函数)参数 SQL_RESET_PARAMS释放或直到该语句被释放.将一个参数绑定到一个变量是通过调用函数 SQLBindParameter实现语法如下:SQLBindParameter proto StatementHandle:DWORD,ParameterNumber:DWORD,InputOutputType:DWORD,ValueType:DWORD,ParameterType:DWORD,ColumnSize:DWORD,DecimalDigits:DWORD,ParameterValuePtr:DWORD,BufferLength:DWORD,pStrLenOrIndPtr:DWORDStatementHandle 语句句柄ParameterNumber 参数个数由1开始。这就是ODBC用来判断参数描述符的方法。如果有三个参数则最左边是第一个参数最右边是第三个参数。InputOutputType 表明参数是用来输入还是输出的标志.这里的输入是指ODBC驱动程序将使用参数中获得的值输出是指ODBC驱动程序将在操作结束时将结果放入参数中.大多数情况下,我们使用参数作为输入。而输出参数经常与存储过程有关.这个参数的两个可能值为: SQL_PARAM_INPUT、 SQL_PARAM_INPUT_OUTPUT和SQL_PARAM_OUTPUT(译者:似应为三个参数但原文如此)ValueType 指明用户程序将要绑定到参数的值或缓冲区的类型。可能的类型为一组常数以SQL_C_开头。ParameterType 参数的SQL类型。例如,如果SQL参数是文本字段,我们就在这里填入值SQL_CHAR.查看MSDN中的ODBC程序员指南来获得完整列表(ODBC Programmers reference)。ColumnSize 参数的长度。换句话说可认为是与参数标志符相连接的列(字段)的长度.在我们的例子中, 我们的参数标志符对列name使用了标准值.如果该列被定义了20字节长,我们就该在ColumnSize中填入20.DecimalDigits 与参数描述符连接的列的小数位.ParameterValuePtr 指向包含参数数据的缓冲区的指针.BufferLength 由ParameterValuePtr指向的缓冲区的长度.pStrLenOrIndPtr 指向一个双字的指针包含以下之一:由ParameterValuePtr指向的缓冲区中包含的参数长度. 除非参数的类型是字符串或二进制值否则这个值被忽略.别把它与BufferLength混淆看一下这个例子就会明白假设该参数是一个字符串该列有20字节宽.所以我们分配了一个21字节长的缓冲区并将其地址传送到ParameterValuePtr。在调用函数SQLExecute前, 我们在缓冲区中放入了字符串Bob.这个字符串有3字节长因此我们需要在pStrLenOrIndPtr指向的双字中放入3这个值.SQL_NTS. 这个参数是一个0结尾字符串(null-terminated string).SQL_NULL_DATA. 参数值为NULL.SQL_DEFAULT_PARAM. 存储过程将使用参数的默认值,而不是从用户程序中获得的值. 它仅适用于已定义了默认参数值的存储过程.SQL_DATA_AT_EXEC. 参数的数据将由SQLPutData传送. 由于数据可能太大无法放入内存(比如整个文件的数据),我们可以告诉ODBC驱动程序我们将用SQLPutData替代.可能你会说 pStrLenOrIndPtr的参数太多了,但通常情况下我们只会用到第一或第三个选项。例子:.dataSQLString db select telephoneNo from employee where name?,0Sample1 db Bob,0Sample2 db Mary,0.data?buffer db 21 dup(?)StrLen dd ?.code........invoke SQLPrepare, hStmt, addr SQLString,sizeof SQLStringinvoke SQLBindParameter, hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, addr buffer, sizeof buffer, addr StrLen;; First run;invoke lstrcpy, addr buffer, addr Sample1mov StrLen, sizeof Sample1invoke SQLExecute, hStmt;; Second run;invoke lstrcpy, addr buffer, addr Sample2mov StrLen, sizeof Sample2invoke SQLExecute, hStmt注意我们仅将参数与缓冲区仅绑定了一次当我们修改了缓冲区的内容并调用了SQLExecute 很多次.不必再调用SQLPrepare.ODBC驱动程序知道去那里找它需要的参数因为已通过SQLBindParameter函数告诉了它.但现在我们还不能获得查询结果.访问和适用结果集是下一章的内容。假设我们已完成了很多SQL语句并要执行一个新的语句那么没必要重新分配一个语句句柄.只要使用SQL_UNBIND与SQL_RESET_PARAMS参数调用SQLFreeStmt函数来解除与参数的绑定就可以了. 接下来就可以接着使用原来的语句句柄来执行SQL语句了.释放语句由调用SQLFreeHandle函数实现.译注原标题为Preparing and Using Statements,因为ODBC驱动程序繁多有解释、编译执行之分所以Preparing不仅是指准备也有预编译的意思。另:关于作者提到的MSDN,其ODBC部分可在Visual Studio及其部件中找到如C:\program Files\DevStudio\SharedIDE\Help\ODBC.hlp.