实验4嵌入式SQL和ODBC的使用.docx

上传人:b****3 文档编号:11094488 上传时间:2023-05-29 格式:DOCX 页数:38 大小:314.26KB
下载 相关 举报
实验4嵌入式SQL和ODBC的使用.docx_第1页
第1页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第2页
第2页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第3页
第3页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第4页
第4页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第5页
第5页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第6页
第6页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第7页
第7页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第8页
第8页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第9页
第9页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第10页
第10页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第11页
第11页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第12页
第12页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第13页
第13页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第14页
第14页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第15页
第15页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第16页
第16页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第17页
第17页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第18页
第18页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第19页
第19页 / 共38页
实验4嵌入式SQL和ODBC的使用.docx_第20页
第20页 / 共38页
亲,该文档总共38页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

实验4嵌入式SQL和ODBC的使用.docx

《实验4嵌入式SQL和ODBC的使用.docx》由会员分享,可在线阅读,更多相关《实验4嵌入式SQL和ODBC的使用.docx(38页珍藏版)》请在冰点文库上搜索。

实验4嵌入式SQL和ODBC的使用.docx

实验4嵌入式SQL和ODBC的使用

实验4嵌入式SQL和ODBC的使用

实验人:

田超(31311039)黄伟(31311064)

实验目的

1.熟悉ODBC的配置和使用

2.熟悉嵌入式SQL编程

3.巩固SQL的知识

实验平台

1.OS:

WindowsXP

2.DBMS:

SQLServer2000

3.Compiler:

VisualC++6.0

预备知识

1)嵌入式SQL编程:

嵌入式SQL由SQL语句和C/C++代码组成。

其中SQL语句由预处理器翻译成C或C++的源代码。

对预处理后的源代码进行编译、连接生成可执行程序后方可运行。

●SQL预处理器

SQLServer的预处理程序是nsqlprep.exe。

其常用的语法格式如下:

nsqlprep程序文档名

⏹nsqlprep详细的语法格式以及参数意义,请看联机帮助。

经查阅联机帮助,nsqlprep的语法格式如下:

nsqlprepprogram_file_name[/SQLACCESS|/NOSQLACCESS]

[/FLAGGER{ENTRY|NONE}][/DB[server_name.]database_name

/PASS{login[.password]|$INTEGRATED}][/BINDfile_name]

[/MSGfile_name][/NOLOGO][/PLANname][/NOLINES]

[/user_defined_option]

⏹要求程序文档名的后缀为.sqc,可以省略。

⏹预编译后得到的文档,与程序文档同名,后缀为.c;放在与程序文档名同一个路径下

nsqlprep.exe在SQLServer的安装目录的MSSQL\Binn下。

在本机中SQLServer的安装目录是C:

\ProgramFiles\MicrosoftSQLServer,nsqlprep.exe在C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn。

由于默认的安装方式(典型安装)并没有安装应用程序nsqlprep.exe,因此,需要把本机中E:

\院内学习工作\大三\数据库\SQLServer2000个人版\x86\binn目录下的内容拷贝到该目录下。

●连接方式

经预处理后的c文件就可以用c的编译器进行编译连接了。

使用VisualC++6.0进行编译连接,连接方式是动态连接,用到动态链接库SQLakw32.dll,sqlaiw32.dll;此两文件已经随同binn.rar的其他内容,被拷贝到C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn下;但仍然需要把该路径加到系统的路径变量中,以使得程序运行时能找到这两个文件。

方法1:

把该两文件拷贝到操作系统目录下的子目录system32中

方法2:

把C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn加到系统环境变量path中。

“我的电脑”->“属性”->“高级”->“环境变量”->“path,编辑”,如下图所示:

在变量值中加入该路径值;注意,路径间用分号”;”分开。

在实验过程中发现如果只做第二步,在之后的运行过程中会报错,只有将方法一也执行了这个连接的准备工作才算是正式完成。

2)通过ODBC访问数据库:

配置ODBC,为SQLServer添加数据源。

如下图所示:

初始化环境:

1.SQLServer2000为其嵌入式SQL提供了一些特殊的接口;默认的安装方式(典型安装)并没有安装这些接口;因此,需要把devtools.rar解压到SQLServer的系统目录下(注意,不是安装目录);本机是把操作系统安装在C盘,则SQLServer的系统目录则是C:

\ProgramFiles\MicrosoftSQLServer。

2.初始化SQLServer的预编译环境。

⏹初始化VisualC++6.0编译器环境,运行文件:

\MicrosoftVisualStudio\VC98\Bin\VCVARS32.BAT

这个过程要在DOS下运行才有效,即找vcvars32.bat的路径,在DOS下运行。

具体步骤如下:

⏹初始化SQLServer的预编译环境,运行文件:

\devtools\samples\esqlc\setenv.bat。

运行方式与vcvars32.bat相同,结果如下:

3.初始化VisualC++6.0环境。

⏹Tools->options->directories->Include

Files:

C:

\ProgramFiles\MicrosoftSQLServer\devtools\include

⏹Tools->options->directories->Lib

Files:

C:

\ProgramFiles\MicrosoftSQLServer\devtools\x86lib

注意:

这些路径需要设为第一项。

如下图所示:

⏹Project->Settings->Link->Object/LibraryModules,添加库文件:

SQLakw32.lib,Caw32.lib

注意,两个文件之间用空格分开。

以上部分均在上机课上在师姐的指导下完成。

实验活动

1.阅读和分析程序esql.sqc,解释程序的主要内容和主要数据结构。

程序的主要内容:

嵌入式SQL的使用,将SQL嵌入到C语言中,在SQL的数据库中通过SELECT语句获取数据,并将获得的信息通过主变量传递给主语言并打印输出。

给出的程序中将程序连接到WXF的SQL服务器上的pubs数据库上,查询满足以下SELECT语句的数据信息:

selectEmployeeIDfromorderswhereOrderID=345

查询得到的结果由主变量EmployeeID传给主语言(C语言),C语言得到数据信息后打印输出。

程序分为以下几块:

1)主变量的声明:

在EXECSQLBEGINDECLARESECTION;和EXECSQLENDDECLARESECTION;之间声明主变量EmployeeID。

2)连接到DBMS:

连接到数据库的管理系统以便从中查询登陆的数据库。

连接到数据库的语法为:

EXECSQLCONNECTTOSQLServer.DataBaseNameUSERlogName.passwd

3)查错:

为了更好的判断和查找错误以修改程序,所以在每次执行完SQL语句后都应该对sqlca所返回的状态值加以判断。

若sqlcode等于0,则输出建立成功信息,否则报错。

4)执行查询:

在这里嵌入SQL的查询语句EXECSQLselectEmployeeIDINTO:

EmployeeIDfromorderswhereOrderID=345,并通过主变量EmployeeID返回查询到的结果,打印结果。

5)断开所有连接:

执行完所有的数据库的访问后,断开所有的连接以释放系统资源。

语法为:

EXECSQLDISCONNECTALL;

数据结构:

主要为在数据库中存储的表,及针对表进行的查找。

2.对程序esql.sqc作适当的修改,使之可以在本地系统上可以运行。

进行预处理、编译、连接(lib连接),查看运行结果。

1)修改:

只需要对连接的服务器及数据库进行修改即可:

EXECSQLCONNECTTOSKY.pubsUSERabc.abc;

同时由于pubs数据库中没有orders表,所以对SELECT语句也作了修改如下:

EXECSQLselectemp_idINTO:

EmployeeIDfromemployeewherelname='Accorti';

2)进行预处理:

将esql.sqc文件放在C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn目录下,运行cmd,进入C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn目录,用nsqlprepesql.sqc的方式运行该文件,可以在C:

\ProgramFiles\MicrosoftSQLServer\MSSQL\Binn中找到预编译后生成的.c文件。

运行过程显示如下:

3)连接操作已经在前面的初始化环境过程中完成。

运行结果如下:

不知为什么,在黄伟的机子上运行时,不管怎么换查询条件,结果总是0

但是在田超的机子上运行的时候,就能够得出正确结果。

田超查询的是Northwind数据库中的orders表,语句为EXECSQLselectEmployeeIDINTO:

EmployeeIDfromorderswhereOrderID=10248;

运行结果如下:

经反复实验,首先排除了黄伟机子的问题,因为在田超的机器上运行也是0。

于是又开始怀疑是数据库的问题。

首先在程序中打印出了sqlcode,如图:

看到sqlcode<0,说明这个语句没有被执行。

开始以为是用户没有访问数据库的权限的问题,但是发现把用户改成sa,把默认数据库改为pubs依然存在这个问题。

将田超的sqc文件和黄伟的放在一起比较,最终发现原来是因为pubs数据库中emp_id的数据类型是empid,而在c中定义的主变量是int型,两者类型不匹配,造成了错误。

黄伟机子上的正确结果:

4)出现的怪异问题:

尽管之前的准备步骤都已经全部做完,但是在预编译时总是会出现以下问题,

每次都要重新把安装文件下的BIN和DEVTOOLS重新拷一遍到C盘SQLSERVER相应得路径下,然后再在DOS下运行setenv.bat和vcvars32.bat两个文件才能解决这个问题,有时甚至所有步骤都要重新做一次。

不明白这是什么原因。

我们在网上查到.bat格式的文件是批处理文件,它在日常的应用中可以发挥巨大的作用,但批处理命令执行的效率比较低,而且不小心会把里面的命令破坏掉。

所以不知是不是因为.bat的稳定性不好。

思考:

●sqlca结构中主要的数据项有哪些?

我们常用的有哪些?

sqlca是一个含有错误变量和状态指示符的数据结构。

通过检查sqlca,应用程序能够检查出嵌入式SQL语句是否成功,并根据成功与否决定是否继续往下执行。

与编译器自动在嵌入SQL语句中包含SQLCA数据结构。

从联机帮助上我们可以找到,SQLCA结构中主要的数据项如下(用结构体表示):

在SQLCA中我们经常用到的是sqlcode,它用来记录最近执行的SQL状态:

"0":

表示该SQL语句被正确执行,无错误发生

>0:

表示执行了该语句,但遇到了错误

<0:

表示由于数据库、系统、网络或应用程序错误等等原因未执行该语句

●SQL操作的常见的错误类型有哪些?

如何得到错误信息?

举例说明

SQL中常见的错误类型有:

通过下面的这些返回值,可以得到相应的出错信息。

例子是我们上面黄伟机子上出现的问题,当时sqlcode返回值为-10039,我觉得它代表的应该是类型不匹配的错误,但不知道为什么,在下面这张表(联机丛书)里查不到这个值

Messagenumber

Runtime/

compiletime

Description

-4998

C

Attempttoconnecttothespecifieddatabaseserverfailed.

-19031

C

Unabletoopenbindfile.

-19051

C

Toomanysections.

-19101

R

Statementtoolong.

-19103

R

Illegal%svalue%s.

Nonnumeric%svalue%s.

(Invalidnumberforthetime-outvalue.)

-19104

R/C

IncorrectSQLstatementsyntax.

-19199

C

ESQLkeyword(s)detectedinPREPAREstatement.

-19306

C

Hostvariableusedbutnotdeclared.

-19313

R

Toofewhostvariables.

-19324

C

Hostvariablemaynotbeusedinthiscontext.

-19408

R

InvalidSQLdatatypeforSQL_TYP_DECIMAL.

-19413

R

Dataoverflowoccurredduringdecimaldataconversion.

-19422

R

UnknownSQLServerdatatype.

-19423

R

Invaliddestinationdatatype.

-19501

R

Nocursordeclared.

-19505

C

Duplicatecursorname:

%s.

-19508

R

Cursornotpositionedonarow.

-19514

R

Cursornotprepared.

-19517

R

Cursoropenattemptedfornon-SELECTpreparedstatement.

-19521

R

Opencursorfailureforsection%dofplans.

-19523

R

Failuretolocate/closecursor.Section%d,plan%s.

-19524

R

Tableforthiscursornotupdatable.

-19525

R

Attempttofetchonunopenedcursor.

-19526

R

Noaccessplanforthiscursor.

-19527

R

Couldnotgetsectionforthiscursor.

-19528

R

Connectionforsection%dofplan%shasNULLDBPROCESS.

-19701

R

NULLconnectionname.

 

 

Connection%snotfound.

-19702

R

Connectionnamenotfound.

 

 

Attempttoclosenonexistentconnection.

-19703

R

FailedtogetDBPROCESS.

Autoconnectfailure.

-19706

R

Loginfailureinsection%d.

-19707

R

Duplicateconnectionname.

-19822

R

ImproperlyinitializeduserSQLDA.

-19911

C

TheSQLdatatypespecifiedforahostvariableisinvalid.

-19913

C

Thetokenidentifierhasalreadybeenused.

-19917

C

Invalidorincorrectoptiontosqlainit().

-19946

C

Cursor%snotdeclared.

-19953

C

Invalidcalltype.

-19955

R

Textnotfoundin%ssection%u.

-19956

R

Accessplansectionorstatementtextnotfound.

-19957

R

Accessplanorstatementtextnotfound.

-19994

R

CannotrunnextBEGINDECLAREsections.Statementignored.

-19995

R

ENDDECLAREencounteredwithoutprecedingBEGINDECLAREstatement.Statementignored.

-19999

C

Aninternalerroroccurred.

连接DBMS错误

通过sqlca中的变量sqlcode的返回值获得错误信息,当返回值为0时,表示连接成功,否则,连接失败。

例如esql.sqc中用以下语句获得错误信息:

if(SQLCODE==0)

{

printf("ConnectiontoSQLServerestablished\n");

}

else

{

//连接DBMS错误

printf("ERROR:

ConnectiontoSQLServerfailed\n");

return

(1);

}

●如何处理SQL操作的错误信息?

a)对于DBMS连接错误:

检查连接是否正常:

1)看SQL服务器是否启动

2)所连接的数据库是否存在

3)登录用户是否具备相应的权限(登录用户的数据库角色)

4)网络连接端口(1433)是否打开

b)用sqlcode:

在程序的error段输入如下语句:

error:

printf("错误%d\n",SQLCODE);

根据sqlcode的值查看联机帮助,根据在联机帮助上查到的错误信息检查相应的SQL语句,针对性的进行修改,直到其能正确运行

c)WHENEVER语句:

在每条嵌入式SQL语句之后立即编写一条检查SQLCODE值的程序是一件很繁琐的事情,为了简化错误处理,可以使用WHENEVER语句:

WHENEVER是说明语句,不是可执行语句,不返回SQLCODE,只是根据SQLCA中的返回码指定相应的措施。

它通知预编译程序在每条可执行嵌入式SQL语句之后自动生成错误处理程序,并指定了错误处理操作。

用户可以使用WHENEVER语句通知预编译程序去如何处理三种异常处理:

lWHENEVERSQLERRORaction:

表示一旦sql语句执行时遇到错误信息,则执行action,action中包含了处理错误的代码(SQLCODE<0)。

lWHENEVERSQLWARNINGaction:

表示一旦sql语句执行时遇到警告信息,则执行aciton,即action中包含了处理警报的代码(SQLCODE=1)。

lWHENEVERNOTFOUND:

表示一旦sql语句执行时没有找到相应的元组,则执行action,即action包含了处理没有查到内容的代码(SQLCODE=100)。

针对上述三种异常处理,用户可以指定预编译程序采取以下三种行为(action):

lWHENEVER…GOTO:

通知预编译程序产生一条转移语句。

lWHENEVER…CONTINUE:

取消先前的WHENEVER语句的作用,通知预编译程序让程序的控制流转入到下一个主语言语句。

lWHENEVER…CALL:

通知预编译程序调用函数。

例如:

EXECSQLWHENEVERSQLERRORGOTOer1

EXECSQLINSERTINTOstudentVALUES(‘s1’,..)

EXECSQLINSERTINTOstudentVALUES(‘s2’,..)

经过预编译后会转换为以下语句:

EXECSQLINSERTINTOstudentVALUES(‘s1’,..)

If(sqlca.sqlcode<0)gotoer1;

EXECSQLINSERTINTOstudentVALUES(‘s2’,..)

If(sqlca.sqlcode<0)gotoer1;

出错处理函数如下:

voidhSQLError(char*msg)

{

printf("\n%s,%ld,%s\n",msg,sqlca.sqlcode,(char*)sqlca.sqlerrm.sqlerrmc);

EXECSQLROLLBACKRELEASE;

exit(-1);

}

●如何断开连接,并释放资源清除环境?

建议尝试程序esql.sqc的方法以外的别的方法。

释放资源清除环境:

EXECSQLCOMMITWORKRELEASE;

断开连接:

EXECSQLDISCONNECTALL;//断开所有连接

EXECSQLDISCONNECTconnection_name;//如果在连接时定义了连接名,则可通过断开连接名来断开连接

(如定义了EXECSQLCONNECTTOSKY.pubsASMyconnectionUSERsa.sa;就可以通过EXECSQLDISCONNECTMyconnection断开和数据库pubs的连接,此语句对和其他数据库的连接无效)

EXECSQLDISCONNECTCURRENT;//表示断开当前连接

3.阅读和分析程序odbc.cpp,解释程序的主要内容和主要数据结构。

程序的主要内容:

在连接到的数据源上查询sno=’s1’的sname和city.

程序主要分为以下几块:

以下为程序开始部分:

1)定义retcode,henv,hdbc,hstmt四个变量,分别对应错误返回码,环境句柄,数据库连接句柄,语句句柄;

2)用SQLAllocHandle分配环境变量,同时用SQLSetEnvAttr告诉odbc这是一个odbc3.0的应用程序;

3)用SQLAllocHandle分配连接句柄;

4)用SQLConnect连接数据库;

以下为程序主体部分:

5)使用SQLAllocHandle分配语句句柄;

6)用SQLExecDirect或别的语句执行表的创建,查询,及修改;

7)用SQLBindCol把某个结果属性列绑定到变量上,用SQLFetch获取查询信息;或是用SQLFetch和SQLGetData来获取查询信息。

以下为程序结束部分,释放所有句柄和环境空间:

8)用SQLFreeHandle释放语句句柄;

9)用SQLDisconnect断开连接;

10)用SQLFreeHandle释放连接句柄

11)用SQLFreeHandle释放环境句柄

心得:

在程序中申请三个句柄的过程是环环相扣的,系统在分配句柄的过程中要用到以前句柄的参数。

而在释放句柄的时候,是要按照申请句柄的逆序来逐一释放的。

程序的主要数据结构:

我认为是三个句柄以及在处理结果的时候SQLBindCol(或SQLGetData)函数所开辟的缓冲区。

4.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2