再现理想 发表于 2015-1-16 22:26:49

MSSQL编程:筹办与利用语句

线上或者测试环境经常出现的误操作总是让DBA同学那么闹心。语句筹办与利用语句
持续我们的进修,在这一章,我们来看看怎样经由过程ODBC来操纵数据源.

在上一章,我们已进修了第一步,如何毗连一个数据源。一个毗连界说了用户与数据源的数据通道.它是静态的.假如要想操纵数据源,我们就必需利用语句(statement).能够以为语句就是发给数据源的命令.这个"命令"必需用SQL写成.经由过程利用语句,我们就能够修正数据源的布局、在个中实行查询、修正及删除数据.

筹办及利用语句可分为以下几个步骤:
分派一个语句句柄(statementhandle)创立SQL语句实行语句烧毁语句分派一个语句句柄
能够经由过程挪用函数SQLAllocHandle来分派一个语句句柄。例子以下:

.data?
hStmtdd?

.code
......
invokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt
创立SQL语句
这部分你就得靠本人了你必需晓得SQL的语法.好比说,当你想创立一个表时,你就得晓得CREATETABLE语句.
实行语句
实行语句有四种办法,由它们是不是被数据库引擎编译过(筹办好)及被如何界说有关.
间接实行(DirectExecution)由用户程序界说SQL语句.语句在运转时(runtime)被编译并实行.编译实行(PreparedExecution)也是由用户程序界说SQL语句,但编译和实行被分为两步:起首SQL被筹办好(被编译),接上去被实行.经由过程这类办法,我们能够只编译SQL语句一次但实行不异的语句屡次以节俭工夫.存储历程(Procedures)SQL语句被编译并寄存在数据源内,用户程序能够在运转时挪用这些语句.目次(Catalog)SQL被硬编码(hardcoded)在ODBC驱动程序内.目次函数的目标是前往预界说的了局集比方数据库中的一切表名.总的来讲,目次函数用来取得数据源的信息的用户程序能够在运转时挪用它们.
这四种办法各有优弱点.当你只运转某一SQL语句一次时,间接实行是一个很好的选择;假如你要常常运转某一语句,则应首选编译实行由于SQL语句仅在第一次运转时被编译,在接上去的运转中,它将运转更快,由于已被编译过了;存储历程是注意速率的最好选择,由于它已被编译过并寄存在数据源中了。弱点是并非一切的数据存储都撑持存储历程.目次次要是是用来取得数据源布局的一些信息。

在本章中,我们次要看一下间接实行和编译实行,由于它们是由我们的程序来完成的.编写存储历程是DBMS(数据库办理体系)的事.而目次将在稍后会商.
间接实行
要间接并疾速实行SQL语句,以以下语法挪用函数SQLExecDirect:

SQLExecDirectprotoStatementHandle:DWORD,
pStatementText:DWORD,
TextLength:DWORD
StatementHandle.要利用的语句句柄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来设置语句属性。
例子:

.data
SQLStmtdb"select*fromSales",0

.data?
hStmtdd?

.code
.....
invokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt
.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
invokeSQLExecDirect,hStmt,addrSQLStmt,sizeofSQLStmt
编译实行
SQL的实行被分为两步:第一步,必需经由过程挪用函数SQLPrepare来*筹办*语句。第二步,经由过程挪用SQLExecute函数来实行语句.在利用编译实行时,我们能够屡次挪用SQLExecute来实行统一语句.分离利用SQL参数,这个办法对实行统一语句极其无效。

SQLPrepare与SQLExecDirect利用不异的三个参数,以是这里不再写出函数原型。SQLExecute语法:

SQLExecuteprotoStatementHandle:DWORD

只须这一个参数,我想不再必要注释了;)

例子:

.data
SQLStmtdb"select*fromSales",0

.data?
hStmtdd?

.code
.....
invokeSQLAllocHandle,SQL_HANDLE_STMT,hConn,addrhStmt
.ifax==SQL_SUCCESS||ax==SQL_SUCCESS_WITH_INFO
invokeSQLPrepare,hStmt,addrSQLStmt,sizeofSQLStmt
invokeSQLExecute,hStmt

你大概会想,编译实行没甚么强于间接实行的。下面的例子还不分明。我们必要晓得SQL语句的参数来细心研讨它。
语句参数(StatementParameters)
这里的参数是指由SQL语句利用的变量.好比说我们有一个叫做"employee"的表,它有三个字段:"name","surname"和"TelephoneNo"。如今我们要找一个叫做"Bob"的人员的德律风号码,就能够利用以下SQL语句:

selecttelephoneNofromemployeewherename=Bob

这条SQL语句象我们但愿的那样事情了。可是,假如我们又想找另外一个人员的德律风号码怎样办?假如不利用参数,那只好再写一条SQL语句,然后再一次编译、实行它。

如今我们不会同意这类低效力的举动了。我们可使用参数来完成方针。在下面的例子中,我们必需将字符串/值交换为?(被称为参数标记符(parametermarker)).SQL语句将酿成如许:

selecttelephoneNofromemployeewherename=?

如今想一下这个成绩:ODBC驱动程序怎样晓得用甚么值来交换参数标记符??谜底是:我们必需供应必要的值.这类办法被称为参数绑定(parameterbinding).复杂点说,就是将一个参数标记符与用户程序中的变量创建毗连的历程.在下面的例子中,我们必要创立一个缓冲区来告知ODBC驱动程序,当它必要一个参数的详细值时,将从我们供应的字符串缓冲区中取得。一旦一个参数与一个变量绑定,它将一向坚持绑定,直到被绑定到另外一变量,或直到一切参数都被函数SQLFreeStmt以(函数)参数SQL_RESET_PARAMS开释,或直到该语句被开释.

将一个参数绑定到一个变量是经由过程挪用函数SQLBindParameter完成,语法以下:

SQLBindParameterprotoStatementHandle:DWORD,
ParameterNumber:DWORD,
InputOutputType:DWORD,
ValueType:DWORD,
ParameterType:DWORD,
ColumnSize:DWORD,
DecimalDigits:DWORD,
ParameterValuePtr:DWORD,
BufferLength:DWORD,
pStrLenOrIndPtr:DWORD
StatementHandle语句句柄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程序员指南来取得完全列表(ODBCProgrammersreference)。ColumnSize参数的长度。换句话说,可以为是与参数标记符相毗连的列(字段)的长度.在我们的例子中,我们的参数标记符对列"name"利用了尺度值.假如该列被界说了20字节长,我们就该在ColumnSize中填进20.DecimalDigits与参数形貌符毗连的列的小数位.ParameterValuePtr指向包括参数数据的缓冲区的指针.BufferLength由ParameterValuePtr指向的缓冲区的长度.pStrLenOrIndPtr指向一个双字的指针,包括以下之一:由ParameterValuePtr指向的缓冲区中包括的参数长度.除非参数的范例是字符串或二进制值,不然这个值被疏忽.别把它与BufferLength搅浑,看一下这个例子就会分明:假定该参数是一个字符串,该列有20字节宽.以是我们分派了一个21字节长的缓冲区,并将其地点传送到ParameterValuePtr。在挪用函数SQLExecute前,我们在缓冲区中放进了字符串"Bob".这个字符串有3字节长,因而我们必要在pStrLenOrIndPtr指向的双字中放进3这个值.SQL_NTS.这个参数是一个0开头字符串(null-terminatedstring).SQL_NULL_DATA.参数值为NULL.SQL_DEFAULT_PARAM.存储历程将利用参数的默许值,而不是从用户程序中取得的值.它仅合用于已界说了默许参数值的存储历程.SQL_DATA_AT_EXEC.参数的数据将由SQLPutData传送.因为数据大概太年夜没法放进内存(好比全部文件的数据),我们能够告知ODBC驱动程序我们将用SQLPutData替换.

大概你会说pStrLenOrIndPtr的参数太多了,但一般情形下,我们只会用到第一或第三个选项。
例子:

.data
SQLStringdb"selecttelephoneNofromemployeewherename=?",0
Sample1db"Bob",0
Sample2db"Mary",0

.data?
bufferdb21dup(?)
StrLendd?

.code
........
invokeSQLPrepare,hStmt,addrSQLString,sizeofSQLString
invokeSQLBindParameter,hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,20,0,addrbuffer,sizeofbuffer,addrStrLen
;===========================================
;Firstrun
;===========================================
invokelstrcpy,addrbuffer,addrSample1
movStrLen,sizeofSample1
invokeSQLExecute,hStmt
;===========================================
;Secondrun
;===========================================
invokelstrcpy,addrbuffer,addrSample2
movStrLen,sizeofSample2
invokeSQLExecute,hStmt


注重我们仅将参数与缓冲区仅绑定了一次,当我们修正了缓冲区的内容并挪用了SQLExecute良多次.不用再挪用SQLPrepare.ODBC驱动程序晓得往那边找它必要的参数由于已经由过程SQLBindParameter函数告知了它.

但如今我们还不克不及取得查询了局.会见和合用了局集是下一章的内容。

假定我们已完成了良多SQL语句,并要实行一个新的语句,那末没需要从头分派一个语句句柄.只需利用SQL_UNBIND与SQL_RESET_PARAMS参数挪用SQLFreeStmt函数来排除与参数的绑定就能够了.接上去就能够接着利用本来的语句句柄来实行SQL语句了.
开释语句
由挪用SQLFreeHandle函数完成.





译注:原题目为PreparingandUsingStatements,由于ODBC驱动程序单一,有注释、编译实行之分,以是Preparing不但是指筹办,也有预编译的意义。另:关于作者提到的MSDN,其ODBC部分可在VisualStudio及其部件中找到,如
C:programFilesDevStudioharedIDEHelpODBC.hlp.MySQL是一个开放源码的小型关联式数据库管理系统,开发者为瑞典MySQLAB公司。目前MySQL被广泛地应用在Internet上的中小型网站中。

飘飘悠悠 发表于 2015-1-19 12:44:11

可以动态传入参数,省却了动态SQL的拼写。

老尸 发表于 2015-1-25 16:34:58

可能有的朋友会抱怨集成的orderby,其实如果使用ranking函数,Orderby是少不了的。如果担心Orderby会影响效率,可以为orderby的字段建立聚集索引,查询计划会忽略orderby操作(因为本来就是排序的嘛)。

海妖 发表于 2015-2-3 10:01:48

语句级快照和事务级快照终于为SQLServer的并发性能带来了突破。个人感觉语句级快照大家应该应用。事务级快照,如果是高并发系统还要慎用。如果一个用户总是被提示修改不成功要求重试时,会杀人的!

不帅 发表于 2015-2-8 20:16:04

另一个是把SQL语句写到服务器端,就是所谓的SP(存储过程);

愤怒的大鸟 发表于 2015-2-26 04:13:03

如果你是从“学习某一种数据库应用软件,从而获得应聘的资本和工作机会”的角度来问的话。

小妖女 发表于 2015-3-8 11:51:34

如果你是从“学习某一种数据库应用软件,从而获得应聘的资本和工作机会”的角度来问的话。

若天明 发表于 2015-3-15 22:29:47

另一个是把SQL语句写到服务器端,就是所谓的SP(存储过程);

冷月葬花魂 发表于 2015-3-22 17:21:08

having子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having条件显示特定的组,也可以使用多个分组标准进行分组。
页: [1]
查看完整版本: MSSQL编程:筹办与利用语句