本文介绍了用HTML(HypertextMakeupLanguage)编写界面、编写ISAPI(InternetServerApplicationProgrammingInterface)交互程序以实现向用MicrosoftSQLServer建立的数据库中添加记录的方法。 1、前言 MicrosoftSQLServer是一种可伸缩的、高性能的关系型数据库管理系统(RDBMS),它专为分布式客户机-服务器计算环境而设计。它的内置数据复制功能、强大的管理工具和开放式的系统体系结构为发布信息提供了一个卓越的平台。它的内置数据复制功能为在整个组织机构内分发准确的信息提供了一个强大且可靠的方式,库中的数据不仅可以复制给MicrosoftSQLServer数据库,也可以复制给ORACLE、IBMDB2、SYBASE和其它数据库。 MicrosoftSQLServer为用户提供的内置数据复制功能--块拷贝程序(bcp)可在数据库管理系统之间迁移数据,能将数据从文件拷贝到SQLServer中。这也就是说用户可以利用bcp把某一个文件中的数据内容添加到数据库中。但是bcp是一个可执行程序,必须在命令提示符(如DOS)下运行它,这给Windows用户带来了极大的不方便;另外bcp命令有其固有的格式并带有许多参数,用户难于记忆。我们发展了利用ISAPI实现向数据库中添加记录的方法。这种方法用HTML编写用户输入文件名的界面,用ISAPI作交互程序。在ISAPI中通过ODBC(OpenDatabaseConnectivity)与SQLServer库连接。用户只需在HTML界面中输入文件名,文件中的数据内容就被方便地添加到指定的表中。此方法克服了bcp命令的缺点。本文介绍了用ISAPI实现向中药数据库中添加记录的方法,并给出了数据库表的建立方法、数据文件的格式、ISAPI主要程序、输入数据文件名界面的HTML文件格式等。 2、数据库表的建立 结构化查询语言SQL(StructuralQueryLanguage)是关系数据库系统的一种高级语言,它是在七十年代末由IBM公司的SanJose研究实验室开发的,现巳被许多关系型数据库管理系统所采用,并被美国国家标准局认定为一种工业标准的关系数据库查询语言。它具有强大的数据维护和查询功能,是一种可工作在多用户系统上的数据子语言。它的命令语句类似于英语句子,用户使用起来十分方便、易于理解。以下是用MicrosoftSQLServer建立的"CMT1"表举例: CREATETABLECMT1 ( ZY00varchar(20)NOTNULL, ZY01varchar(50)NOTNULL, ZY02textNULL, ZY03varchar(80)NOTNULL, ZY04textNULL, ZY05varchar(100)NOTNULL, ZY06varchar(9)NOTNULL, ZY07varchar(5)NOTNULL, ZY08varchar(2)NOTNULL ) 3、数据文件格式 以下是向中药数据库表CMT1中添加记录的数据文件格式: ZY00(中药中文名):{三七} ZY01(中药中文名汉语拼音(大写)):{SANQI} ZY02(中药中文别名):{人参三七,田七,盘龙七(四川),金不换(江西)} ZY03(中药英文名):{Sanchi} ZY04(中药英文别名):{} ZY05(中药拉丁名):{RadixNotoginseng} ZY06(中药材唯一码):{MMH35002A} ZY07(中药大辞典编码):{00096} ZY08(功效类别):{18} 上述数据文件中,只有"{"和"}"符号之间的字符被添加到中药数据库表CMT1的相应数据域中,"{"之前的字符用于给编写数据文件的用户予于提示,在ISAPI程序中可实现只取"{"和"}"之间的字符,忽略"{"前的提示字符及"{"和"}"字符等。 4、ISAPI应用程序的编写 我们利用SQL语句可嵌入在应用程序中的特点,把SQL的有关请求语句嵌入在ISAPI交互程序中。ISAPI交互程序用VisualC++编写,以下是实现向中药数据库的表CMT1中添加记录的主要程序段: //建立一个CZY类的成员函数FileWrite1Entry,实现向中药数据库的表CMT1中添加记录 voidCZY::FileWrite1Entry(CHttpServerContext*pCtxt,LPTSTRpstrFileName) { constunsignedREC_NUM=1; //REC_NUM(数据文件中记录个数) constunsignedLINE=9; //LINE(表中数据域的个数) constunsignedCOLUMN=6000; //COLUMN(每个数据域中字符的最大个数) charc,data[LINE][COLUMN]; FILE*fp; StartContent(pCtxt); //HTML头格式 WriteTitle(pCtxt); //HTML标题 CstringstringSql; CstringstrQuery; CstringstrOutput; CstringpstrZY00,pstrZY01,pstrZY02,pstrZY03,pstrZY04,pstrZY05, pstrZY06,pstrZY07,pstrZY08; //以"读"的方式打开文件名为pstrFileName的文件 if(!(fp=fopen(pstrFileName,"r"))) { *pCtxt <<"<center><fontcolor='red'>Warning:</font>Cannotopenthisfile.</center>"; return; } //从文件中读取数据 for(intk=0;k<REC_NUM;k++) { for(intI=0;I<LINE;I++) { //忽略"{"以前的说明性字符 do{ c=getc(fp); }while(c!='{'); //读取"{"和"}"之间的字符数据 for(intj=0;j<COLUMN;j++) { c=getc(fp); if(c=='}') { data[I][j]='\0'; break; } elseif((c=='\r')||(c=='\n')||(c=='{')) { j--; } else { data[I][j]=c; } } } } fclose(fp) //把从文件中读取的数据赋给相应的字符型变量 pstrZY00=data[0]; pstrZY01=data[1]; pstrZY02=data[2]; pstrZY03=data[3]; pstrZY04=data[4]; pstrZY05=data[5]; pstrZY06=data[6]; pstrZY07=data[7]; pstrZY08=data[8]; //创建数据库对象 Cdatabasedb; //确认数据 if( !strcmp(pstrZY00,NULLSTRING)||!strcmp(pstrZY01,NULLSTRING)|| !strcmp(pstrZY03,NULLSTRING)||!strcmp(pstrZY05,NULLSTRING)|| !strcmp(pstrZY06,NULLSTRING)||!strcmp(pstrZY07,NULLSTRING)|| !strcmp(pstrZY08,NULLSTRING) ) { *pCtxt <<" <center>" <<"PleasebecertaintoenteryourZY00,ZY01,ZY03,ZY05,ZY06,ZY07,ZY08.\r\n" <<"Thankyou." <<"</center>"; return; } //格式化添加记录的条件 strQuery.Format("ZY00='%-.20s'",pstrZY00); //打开数据库对象,如果此对象不存在就退出 if(!db.Open(ZyDB,//lpszDSN FALSE,//bExclusive FALSE,//bReadOnly CONNECTSTRING,//lpszConnect FALSE))//bUseCursorLib { *pCtxt<<"Couldnotopenthedatabase."; return; } //创建RECOREDSET类的数据库表对象 CZyCMT1rsZy(&db); //指定格式化的添加记录的条件给表对象 rsZy.m_strFilter=strQuery; //打开表对象,如果不能打开就CATCH异常处理 try { if(rsZy.Open(Crecordset::dynaset)) { //如果想添加的记录已经存在于数据库的表中,就给出IDS_ONFILE中包含的反馈信息 if(!rsZy.IsBOF()) { strOutput.Format(IDS_ONFILE,pstrZY00,SCRIPTPATH); } else { //构造插入记录语句 stringSql.Format("InsertintoCMT1(ZY00,ZY01,ZY02,ZY03,ZY04,ZY05,ZY06," "ZY07,ZY08)VALUES('%-.20s','%-.50s','%s','%-.80s','%s'," "'%-.100s','%-.9s','%-.5s','%-.2s')",pstrZY00,pstrZY01,pstrZY02,pstrZY03,pstrZY04,pstrZY05,pstrZY06,pstrZY07,pstrZY08); //执行插入记录命令。如果成功给出IDS_THANKYOU中包含的反馈信息, //否则CATCH异常处理 try { db.ExecuteSQL(stringSql); strOutput.Format(IDS_THANKYOU,pstrZY00,SCRIPTPATH); } catch(CDBException*pEX) { TCHARszError[1024]; if(pEX->GetErrorMessage(szError,sizeof(szError))) strOutput.Format(IDS_EXCEPTION,szError,SCRIPTPATH); else strOutput.Format(IDS_UNKNOWN,SCRIPTPATH); } } } else //如果数据库表对象不能打开,给出IDS_UNKNOWN中包含的反馈信息 strOutput.Format(IDS_UNKNOWN,SCRIPTPATH); } catch(CDBException*pEX) { TCHARszError[1024]; if(pEX->GetErrorMessage(szError,sizeof(szError))) strOutput.Format(IDS_EXCEPTION,szError,SCRIPTPATH); else strOutput.Format(IDS_UNKNOWN,SCRIPTPATH); } rsZy.Close(); //关闭表对象 db.Close(); //关闭数据库 //给用户显示反馈的信息 *pCtxt<<strOutput; EndContent(pCtxt); //HTML尾格式 } 编译好的ISAPI动态连接库程序将其置于/Scripts目录中。/Scripts是交互程序的虚拟目录。它可通过WWW服务管理器来设定。当WWW第一次被安装时,缺省的ISAPI可执行的虚拟目录是/Scripts。 5、输入数据文件名界面的编写 HTML文件是在普通文本中插入HTML标识符,WWW浏览器通过识别HTML文件中的标识符,按照HTML文件中的标识符所指定的格式显示文件。下面给出向中药数据库表CMT1中添加记录的输入数据文件名界面的HTML具体写法,此文件取名为FileWrite1.html。 <html> <bodybgcolor="white"> <center> <h2><p><fontcolor="#FF0000">加记录到中药表一</font></p></h2> <hr> <h3>请输入文件名:</h3> <formaction="/scripts/Zy.dll?FileWrite1Entry"method="post"> <p><inputname="FileName"size=40></p> <inputtype="submit"value="提交"> <inputtype="reset"value="重置"> </form> </center> </body> </html> 在Netscape或InternetExplorer的URL中键入http://webserver/FileWrite1.html,其中webserver是服务器名或服务器的域名,屏幕上就会显示输入数据文件名的界面,根据界面提示在表栏中输入数据文件名,提交后反馈信息在客户端的显示 6、结论 我们发展的利用ISAPI向数据库中添加记录的方法不需要在DOS提示符下进行任何操作。另外,我们的数据文件中可包含为编写数据文件的用户加入的提示字符,提示字符并不会加入到数据库中,而MicrosoftSQLServer的bcp命令无法选定忽略数据文件中的任何字符,只能把数据文件中的所有数据拷贝到数据库中。同时,后者需在DOS提示符下操作。 利用ISAPI作交互程序不仅可实现网络数据库查询,而且可对数据库中的记录进行操作(添加、修改、删除等)。随着WindowsNT使用的普及,ISAPI的应用范围将会越来越广泛。 |