﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-        &lt;FONT size=4&gt;&lt;strong&gt;&lt;script src="http://www.codechina.net/comm/tuiguang.php?&gt;说我么？没毕业的小p孩呢，而且还是个败家子&lt;/script&gt;&lt;/strong&gt;&lt;FONT&gt;         -文章分类-数据库编程</title><link>http://www.cppblog.com/dbsky/category/2088.html</link><description>&lt;FONT &gt;&lt;strong&gt;email:&lt;/strong&gt;
&lt;/FONT&gt;
&lt;input type=text name=email value="Guemcit@163.com"&gt;
&lt;/br&gt;&lt;/br&gt;
&lt;strong&gt;&lt;script src="http://www.codechina.net/comm/tuiguang.php?&gt;程序=对象+消息 &gt;&lt;/script &gt;&lt;/strong&gt;
                        </description><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 12:02:15 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 12:02:15 GMT</pubDate><ttl>60</ttl><item><title>［转载］ -&gt; 数据库设计中的技巧</title><link>http://www.cppblog.com/dbsky/articles/9569.html</link><dc:creator>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </dc:creator><author>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </author><pubDate>Sat, 08 Jul 2006 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/dbsky/articles/9569.html</guid><wfw:comment>http://www.cppblog.com/dbsky/comments/9569.html</wfw:comment><comments>http://www.cppblog.com/dbsky/articles/9569.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dbsky/comments/commentRss/9569.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dbsky/services/trackbacks/9569.html</trackback:ping><description><![CDATA[
		<p style="TEXT-INDENT: 2em">1. 原始单据与实体之间的关系 </p>
		<p style="TEXT-INDENT: 2em">可以是一对一、一对多、多对多的关系。在一般情况下，它们是一对一的关系：即一张原始单据对应且只对应一个实体。在特殊情况下，它们可能是一对多或多对一的关系，即一张原始单证对应多个实体，或多张原始单证对应一个实体。这里的实体可以理解为基本表。明确这种对应关系后，对我们设计录入界面大有好处。 </p>
		<p style="TEXT-INDENT: 2em">〖例1〗：一份员工履历资料，在人力资源信息系统中，就对应三个基本表：员工基本情况表、社会关系表、工作简历表。这就是“一张原始单证对应多个实体”的典型例子。 </p>
		<p style="TEXT-INDENT: 2em">2. 主键与外键 </p>
		<p style="TEXT-INDENT: 2em">一般而言，一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键，也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 </p>
		<p style="TEXT-INDENT: 2em">主键与外键的设计，在全局数据库的设计中，占有重要地位。当全局数据库的设计完成以后，有个美国数据库设计专家说：“键，到处都是键，除了键之外，什么也没有”，这就是他的数据库设计经验之谈，也反映了他对信息系统核心(数据模型)的高度抽象思想。因为：主键是实体的高度抽象，主键与外键的配对，表示实体之间的连接。 </p>
		<p style="TEXT-INDENT: 2em">3. 基本表的性质 </p>
		<p style="TEXT-INDENT: 2em">基本表与中间表、临时表不同，因为它具有如下四个特性： </p>
		<p style="TEXT-INDENT: 2em">(1) 原子性。基本表中的字段是不可再分解的。 </p>
		<p style="TEXT-INDENT: 2em">(2) 原始性。基本表中的记录是原始数据（基础数据）的记录。 </p>
		<p style="TEXT-INDENT: 2em">(3) 演绎性。由基本表与代码表中的数据，可以派生出所有的输出数据。 </p>
		<p style="TEXT-INDENT: 2em">(4) 稳定性。基本表的结构是相对稳定的，表中的记录是要长期保存的。 </p>
		<p style="TEXT-INDENT: 2em">理解基本表的性质后，在设计数据库时，就能将基本表与中间表、临时表区分开来。 </p>
		<p style="TEXT-INDENT: 2em">4. 范式标准 </p>
		<p style="TEXT-INDENT: 2em">基本表及其字段之间的关系, 应尽量满足第三范式。但是，满足第三范式的数据库设计，往往不是最好的设计。为了提高数据库的运行效率，常常需要降低范式标准：适当增加冗余，达到以空间换时间的目的。 </p>
		<p style="TEXT-INDENT: 2em">〖例2〗：有一张存放商品的基本表，如表1所示。“金额”这个字段的存在，表明该表的设计不满足第三范式，因为“金额”可以由“单价”乘以“数量”得到，说明“金额”是冗余字段。但是，增加“金额”这个冗余字段，可以提高查询统计的速度，这就是以空间换时间的作法。 </p>
		<p style="TEXT-INDENT: 2em">在Rose 2002中，规定列有两种类型：数据列和计算列。“金额”这样的列被称为“计算列”，而“单价”和“数量”这样的列被称为“数据列”。 </p>
		<p style="TEXT-INDENT: 2em">表1 商品表的表结构 </p>
		<p style="TEXT-INDENT: 2em">商品名称 商品型号 单价 数量 金额 </p>
		<p style="TEXT-INDENT: 2em">电视机 29吋 2,500 40 100,000 </p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">5. 通俗地理解三个范式 </p>
		<p style="TEXT-INDENT: 2em">通俗地理解三个范式，对于数据库设计大有好处。在数据库设计中，为了更好地应用三个范式，就必须通俗地理解三个范式(通俗地理解是够用的理解，并不是最科学最准确的理解)： </p>
		<p style="TEXT-INDENT: 2em">第一范式：1NF是对属性的原子性约束，要求属性具有原子性，不可再分解； </p>
		<p style="TEXT-INDENT: 2em">第二范式：2NF是对记录的惟一性约束，要求记录有惟一标识，即实体的惟一性； </p>
		<p style="TEXT-INDENT: 2em">第三范式：3NF是对字段冗余性的约束，即任何字段不能由其他字段派生出来，它要求字段没有冗余。 </p>
		<p style="TEXT-INDENT: 2em">没有冗余的数据库设计可以做到。但是，没有冗余的数据库未必是最好的数据库，有时为了提高运行效率，就必须降低范式标准，适当保留冗余数据。具体做法是：在概念数据模型设计时遵守第三范式，降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段，允许冗余。 </p>
		<p style="TEXT-INDENT: 2em">6. 要善于识别与正确处理多对多的关系 </p>
		<p style="TEXT-INDENT: 2em">若两个实体之间存在多对多的关系，则应消除这种关系。消除的办法是，在两者之间增加第三个实体。这样，原来一个多对多的关系，现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体，实质上是一个较复杂的关系，它对应一张基本表。一般来讲，数据库设计工具不能识别多对多的关系，但能处理多对多的关系。 </p>
		<p style="TEXT-INDENT: 2em">〖例3〗：在“图书馆信息系统”中，“图书”是一个实体，“读者”也是一个实体。这两个实体之间的关系，是一个典型的多对多关系：一本图书在不同时间可以被多个读者借阅，一个读者又可以借多本图书。为此，要在二者之间增加第三个实体，该实体取名为“借还书”，它的属性为：借还时间、借还标志(0表示借书，1表示还书)，另外，它还应该有两个外键(“图书”的主键，“读者”的主键)，使它能与“图书”和“读者”连接。 </p>
		<p style="TEXT-INDENT: 2em">7. 主键PK的取值方法 </p>
		<p style="TEXT-INDENT: 2em">PK是供程序员使用的表间连接工具，可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时，建议字段的个数不要太多，多了不但索引占用空间大，而且速度也慢。 </p>
		<p style="TEXT-INDENT: 2em">8. 正确认识数据冗余 </p>
		<p style="TEXT-INDENT: 2em">主键与外键在多表中的重复出现, 不属于数据冗余，这个概念必须清楚，事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余！而且是一种低级冗余，即重复性的冗余。高级冗余不是字段的重复出现，而是字段的派生出现。 </p>
		<p style="TEXT-INDENT: 2em">〖例4〗：商品中的“单价、数量、金额”三个字段，“金额”就是由“单价”乘以“数量”派生出来的，它就是冗余，而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性，因为同一数据，可能从不同时间、地点、角色上多次录入。因此，我们提倡高级冗余(派生性冗余)，反对低级冗余(重复性冗余)。 </p>
		<p style="TEXT-INDENT: 2em">9. E--R图没有标准答案 </p>
		<p style="TEXT-INDENT: 2em">信息系统的E--R图没有标准答案，因为它的设计与画法不是惟一的，只要它覆盖了系统需求的业务范围和功能内容，就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案，并不意味着可以随意设计。好的E—R图的标准是：结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。 </p>
		<p style="TEXT-INDENT: 2em">10. 视图技术在数据库设计中很有用 </p>
		<p style="TEXT-INDENT: 2em">与基本表、代码表、中间表不同，视图是一种虚表，它依赖数据源的实表而存在。视图是供程序员使用数据库的一个窗口，是基表数据综合的一种形式, 是数据处理的一种方法，是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。 若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。 </p>
		<p style="TEXT-INDENT: 2em">对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统，视图的作用更加重要。这些系统的基本表完成物理设计之后，立即在基本表上建立第一层视图，这层视图的个数和结构，与基本表的个数和结构是完全相同。并且规定，所有的程序员，一律只准在视图上操作。只有数据库管理员，带着多个人员共同掌握的“安全钥匙”，才能直接在基本表上操作。请读者想想：这是为什么？ </p>
		<p style="TEXT-INDENT: 2em">11. 中间表、报表和临时表 </p>
		<p style="TEXT-INDENT: 2em">中间表是存放统计数据的表，它是为数据仓库、输出报表或查询结果而设计的，有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的，存放临时记录，为个人所用。基表和中间表由DBA维护，临时表由程序员自己用程序自动维护。 </p>
		<p style="TEXT-INDENT: 2em">12. 完整性约束表现在三个方面 </p>
		<p style="TEXT-INDENT: 2em">域的完整性：用Check来实现约束，在数据库设计工具中，对字段的取值范围进行定义时，有一个Check按钮，通过它定义字段的值城。 </p>
		<p style="TEXT-INDENT: 2em">参照完整性：用PK、FK、表级触发器来实现。 </p>
		<p style="TEXT-INDENT: 2em">用户定义完整性：它是一些业务规则，用存储过程和触发器来实现。 </p>
		<p style="TEXT-INDENT: 2em">13. 防止数据库设计打补丁的方法是“三少原则” </p>
		<p style="TEXT-INDENT: 2em">(1) 一个数据库中表的个数越少越好。只有表的个数少了，才能说明系统的E--R图少而精，去掉了重复的多余的实体，形成了对客观世界的高度抽象，进行了系统的数据集成，防止了打补丁式的设计； </p>
		<p style="TEXT-INDENT: 2em">(2) 一个表中组合主键的字段个数越少越好。因为主键的作用，一是建主键索引，二是做为子表的外键，所以组合主键的字段个数少了，不仅节省了运行时间，而且节省了索引存储空间； </p>
		<p style="TEXT-INDENT: 2em">(3) 一个表中的字段个数越少越好。只有字段的个数少了，才能说明在系统中不存在数据重复，且很少有数据冗余，更重要的是督促读者学会“列变行”，这样就防止了将子表中的字段拉入到主表中去，在主表中留下许多空余的字段。所谓“列变行”，就是将主表中的一部分内容拉出去，另外单独建一个子表。这个方法很简单，有的人就是不习惯、不采纳、不执行。 </p>
		<p style="TEXT-INDENT: 2em">数据库设计的实用原则是：在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念，综合观点，不能孤立某一个原则。该原则是相对的，不是绝对的。“三多”原则肯定是错误的。试想：若覆盖系统同样的功能，一百个实体(共一千个属性) 的E--R图，肯定比二百个实体(共二千个属性) 的E--R图，要好得多。 </p>
		<p style="TEXT-INDENT: 2em">提倡“三少”原则，是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成为应用数据库，将应用数据库集成为主题数据库，将主题数据库集成为全局综合数据库。集成的程度越高，数据共享性就越强，信息孤岛现象就越少，整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。 </p>
		<p style="TEXT-INDENT: 2em">提倡“三少”原则的目的，是防止读者利用打补丁技术，不断地对数据库进行增删改，使企业数据库变成了随意设计数据库表的“垃圾堆”，或数据库表的“大杂院”，最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章，不计其数，导致企事业单位的信息系统无法维护而瘫痪。 </p>
		<p style="TEXT-INDENT: 2em">“三多”原则任何人都可以做到，该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的原则，它要求有较高的数据库设计技巧与艺术，不是任何人都能做到的，因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。 </p>
		<p style="TEXT-INDENT: 2em">14. 提高数据库运行效率的办法 </p>
		<p style="TEXT-INDENT: 2em">在给定的系统硬件和系统软件条件下，提高数据库系统的运行效率的办法是： </p>
		<p style="TEXT-INDENT: 2em">(1) 在数据库物理设计时，降低范式，增加冗余, 少用触发器, 多用存储过程。 </p>
		<p style="TEXT-INDENT: 2em">(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条)，复杂计算要先在数据库外面，以文件系统方式用C++语言计算处理完成之后，最后才入库追加到表中去。这是电信计费系统设计的经验。 </p>
		<p style="TEXT-INDENT: 2em">(3) 发现某个表的记录太多，例如超过一千万条，则要对该表进行水平分割。水平分割的做法是，以该表主键PK的某个值为界线，将该表的记录水平分割为两个表。若发现某个表的字段太多，例如超过八十个，则垂直分割该表，将原来的一个表分解为两个表。 </p>
		<p style="TEXT-INDENT: 2em">(4) 对数据库管理系统DBMS进行系统优化，即优化各种系统参数，如缓冲区个数。 </p>
		<p style="TEXT-INDENT: 2em">(5) 在使用面向数据的SQL语言进行程序设计时，尽量采取优化算法。 </p>
		<p style="TEXT-INDENT: 2em">总之，要提高数据库的运行效率，必须从数据库系统级优化、数据库设计级优化、程序实现级优化，这三个层次上同时下功夫。 </p>
		<p style="TEXT-INDENT: 2em">上述十四条技巧或艺术，是许多人在大量的数据库分析与设计实践中，逐步总结出来的。对于这些经验的运用，读者不能生帮硬套，死记硬背，而要消化理解，实事求是，灵活掌握。并逐步做到：在应用中发展，在发展中应用。</p>
<img src ="http://www.cppblog.com/dbsky/aggbug/9569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dbsky/" target="_blank"><FONT color=red>dbsky </FONT> </a> 2006-07-08 10:25 <a href="http://www.cppblog.com/dbsky/articles/9569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ODBC API实现查询mssql2000</title><link>http://www.cppblog.com/dbsky/articles/9339.html</link><dc:creator>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </dc:creator><author>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </author><pubDate>Mon, 03 Jul 2006 12:18:00 GMT</pubDate><guid>http://www.cppblog.com/dbsky/articles/9339.html</guid><wfw:comment>http://www.cppblog.com/dbsky/comments/9339.html</wfw:comment><comments>http://www.cppblog.com/dbsky/articles/9339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dbsky/comments/commentRss/9339.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dbsky/services/trackbacks/9339.html</trackback:ping><description><![CDATA[
		<p>代码如下：<br /><br />//所有的ODBC函数都以SQL开始</p>
		<p>#include &lt;conio.h&gt;//getch()<br />#include &lt;stdio.h&gt;<br />#include &lt;afxwin.h&gt;//// MFC core and standard components<br />#include &lt;sqlext.h&gt; //包含有扩展的ODBC的定义<br />#include &lt;sql.h&gt; //包含有基本的ODBC API的定义<br />#include &lt;odbcinst.h&gt;<br />#pragma comment(lib, "odbc32.lib")<br />#pragma comment(lib, "odbccp32.lib")//SQLConfigDataSource()函数</p>
		<p>//#include "sqltypes.h"<br />//#include "sqlucode.h"<br />//#include "odbcss.h"</p>
		<p>
				<br />int main(int argc, char* argv[])<br />{<br />  <br /> SQLRETURN sr=SQL_SUCCESS;<br /> SQLHENV  hEnv=0; //分配odbc环境<br /> SQLHDBC  hDbc=0;//<br /> SQLHSTMT hStmt;//</p>
		<p> //<br /> SQLINTEGER iID;//第一列<br /> SQLCHAR tmJoin[20];//第二列<br />    SQLCHAR szName[10];//第三列<br /> SQLREAL fTall;//第四列<br /> SQLINTEGER cbID,cbJoin,cbName,cbTall;//保存得到的数据的长度<br /> //<br /> int i=0;<br /> SQLCHAR   SqlState[6]; <br /> SQLINTEGER NativeError; <br /> SQLCHAR ErrMsg[SQL_MAX_MESSAGE_LENGTH]; <br /> //<br /> char szDSN[] = "TestDB";//ODBC数据源 <br /> char szUID[] = "sa"; //SQL用户<br /> char szPWD[] = ""; //口令<br />    LPCSTR svSQL="select * from [ApiOdbc]";</p>
		<p> //创建ODBC句柄,分配odbc环境<br /> /*对于任何ODBC应用程序来说，第一步的工作是装载驱动程序管理器，然后初始化ODBC环境，分配环境句柄。<br />    首先，程序中声明一个SQLHENV类型的变量，然后调用函数SQLAllocHandle，向其中传递分配的上述SQLHENV类型<br /> 的变量地址和SQL_HANDLE_ENV选项。如下代码所示：SQLHENV henv;SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&amp;henv);<br />    执行该调用语句后，驱动程序分配一个结构，该结构中存放环境信息，然后返回对应于该环境的环境句柄。<br /> SQLRETURN SQLAllocHandle(<br />      SQLSMALLINT   HandleType,<br />      SQLHANDLE     InputHandle,第二个参数为输入句柄<br />      SQLHANDLE *   OutputHandlePtr 第三个参数为输出句柄<br />       );  <br /> SQL_HANDLE_ENV：申请环境句柄。<br />    SQL_HANDLE_DBC：申请数据库连接句柄<br /> SQL_HANDLE_STMT：申请SQL语句句柄，每次执行SQL语句都申请语句句柄，并且在执行完成后释放*/<br />    <br /> //利用动态链接库Odbcinst.dll动态创建DSN<br /> if(SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN,"SQL Server","DSN=TestDB\0Description=TestAPIODBC\0SERVER=(local)\0DATABASE=TestDB"))<br /> {<br />  printf("32位ODBC数据源配置 Success!\n\n");<br /> }<br />    <br /> sr = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&amp;hEnv);<br /> if(sr==SQL_SUCCESS||sr==SQL_SUCCESS_WITH_INFO)<br /> {<br />  printf("1~~创建环境句柄SQLAllocHandle Success!\n");<br /> }<br />    //设定odbc版本,将ODBC设置成为版本3，否则某些ODBC API 函数不能被支持<br /> sr = SQLSetEnvAttr(hEnv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER) SQL_OV_ODBC3,SQL_IS_INTEGER); <br /> if(sr==SQL_SUCCESS||sr==SQL_SUCCESS_WITH_INFO)<br /> {<br />  printf("2~~SQLSetEnvAttr Success!\n");<br /> }<br /> //分配odbc连接句柄 <br /> /*分配环境句柄后，在建立至数据源的连接之前，我们必须分配一个连接句柄，每一个到数据源的连接对应于一个连接句柄。<br />    首先，程序定义了一个SQLHDBC类型的变量，用于存放连接句柄，然后调用SQLAllocHandle函数分配句柄。如下代码所示：<br />    SQLHDBC hdbc;SQLAllocHandle(SQL_HANDLE_DBC,henv,&amp;hdbc);henv为环境句柄。*/<br />    sr = SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&amp;hDbc); <br />    if(sr==SQL_SUCCESS||sr==SQL_SUCCESS_WITH_INFO)<br /> {<br />  printf("3~~创建连接句柄SQL_HANDLE_DBC Success!\n");<br /> }<br />    //连接连接属性 <br /> /*当连接句柄分配完成后，我们可以设置连接属性，所有的连接属性都有缺省值，但是我们可以通过调用函数SQLSetConnectAttr()<br /> 来设置连接属性。用函数SQLGetConnectAttr()获取这些连接属性。函数格式如下：<br /> SQLRETURN SQLSetConnectAttr(SQLHDBC ConnectionHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength);<br /> SQLRETURN SQLGetConnectAttr(SQLHDBC ConnectionHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength);<br />    应用程序可以根据自己的需要设置不同的连接属性。*/<br /> sr = SQLSetConnectAttr(hDbc,SQL_ATTR_LOGIN_TIMEOUT,(void*)7,0); <br />    if(sr==SQL_SUCCESS||sr==SQL_SUCCESS_WITH_INFO)<br /> {<br />  printf("4~~设置连接属性SQLSetConnectAttr Success!\n");<br /> }<br /> <br /> //连接 <br /> /*完成对连接属性的设置之后，就可以建立到数据源的连接了。对于不同的程序和用户接口，可以用不同的函数建立连接：<br /> SQLConnect、SQLDriverConnect、SQLBrowseConnect。<br />    SQLConnect该函数提供了最为直接的程序控制方式，我们只要提供数据源名称、用户ID和口令，就可以进行连接了。<br />    函数格式:SQLRETURN SQLConnect(SQLHDBC ConnectionHandle,SQLCHAR ServerName,SQLSMALLINT NameLength1,SQLCHAR UserName,SQLSMALLINT NameLength2,SQLCHAR *Authentication,SQLSMALLINT NameLength3); <br />    参数:ConnectionHandle 连接句柄，ServerName 数据源名称，NameLength1 数据源名称长度，UserName 用户ID<br /> NameLength2 用户ID长度，Authentication 用户口令，NameLength3 用户口令长度<br /> 返回值:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR, or SQL_INVALID_HANDLE. <br /> 成功返回SQL_SUCCESS*/<br /> sr = SQLConnect(hDbc,(SQLCHAR *)szDSN, SQL_NTS,(SQLCHAR *)szUID,SQL_NTS,(SQLCHAR *)NULL,SQL_NTS); <br />    /*如果返回值为SQL_ERROR或SQL_SUCCESS_WITH_INFO，可以用函数SQLGetDiagRec获取相应SQLSTATE的值*/<br /> if(sr != SQL_SUCCESS &amp;&amp; sr != SQL_SUCCESS_WITH_INFO) <br /> {<br />  TRACE("ERROR"); <br />  while(SQLGetDiagRec(SQL_HANDLE_DBC,hDbc,i,SqlState, &amp;NativeError,ErrMsg,sizeof(ErrMsg),NULL)!= SQL_NO_DATA)<br />   TRACE("Diag : %d SQLSTATE :%s NativeError : %d ,ErrMsg : %s\n",i ++,SqlState,NativeError,ErrMsg); <br /> } <br /> else<br /> {<br />  printf("5~~连接Connect Success!\n");<br />    }<br /> //分配语句句柄sr = SQLAllocStmt(hDbc,&amp;hStmt);SQLAllocStmt() 已被废弃，且替换为 SQLAllocHandle()；<br /> sr=SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &amp;hStmt);<br />    if(sr == SQL_SUCCESS||sr == SQL_SUCCESS_WITH_INFO)<br /> {<br />  printf("6~~分配语句句柄SQL_HANDLE_STMT Success!\n");<br /> }</p>
		<p>    //执行SQL查询语句<br /> sr=SQLExecDirect(hStmt,(UCHAR *)svSQL,SQL_NTS);<br />    if (sr == SQL_SUCCESS||sr == SQL_SUCCESS_WITH_INFO) <br />    {<br />        printf("7~~执行SQL查询语句SQLExecDirect Success!\n");<br />  printf("\n-------------get date from db-------------\n");<br />  while ((sr=SQLFetch(hStmt))!=SQL_NO_DATA)<br />  {<br />   //执行SQL语句后遍历结果集来得到数据<br />   SQLGetData(hStmt, 1, SQL_C_ULONG, &amp;iID, 0, &amp;cbID);<br />   SQLGetData(hStmt, 2, SQL_C_CHAR,  tmJoin, 20, &amp;cbJoin);//datatime类型放在SQLCHAR数组中，数组length要足够<br />   SQLGetData(hStmt, 3, SQL_C_CHAR,  szName, 10, &amp;cbName);<br />   SQLGetData(hStmt, 4, SQL_C_FLOAT, &amp;fTall, 0, &amp;cbTall);<br />   printf("%d~~~%s~~~%s~~~%f\n",iID,tmJoin,szName,fTall);<br />  }<br /> }</p>
		<p>    //释放句柄<br /> if(hStmt!=SQL_NULL_HANDLE)<br /> {<br />  SQLFreeHandle( SQL_HANDLE_STMT, hStmt );<br />     hStmt=NULL;<br /> }<br /> if(hDbc != SQL_NULL_HANDLE) <br /> {<br />  sr = SQLDisconnect(hDbc);<br />  SQLFreeHandle(SQL_HANDLE_DBC,hDbc); <br />  hDbc=NULL;<br /> }<br /> if(hEnv != SQL_NULL_HANDLE) <br /> {<br />  SQLFreeHandle(SQL_HANDLE_ENV,hEnv);<br />  hEnv=NULL;<br /> }<br /> //<br /> printf("API ODBC Success!\n");<br /> system("PAUSE");<br /> return 0;<br />}</p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
<img src ="http://www.cppblog.com/dbsky/aggbug/9339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dbsky/" target="_blank"><FONT color=red>dbsky </FONT> </a> 2006-07-03 20:18 <a href="http://www.cppblog.com/dbsky/articles/9339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于MSSQL2000时的部分读书笔记</title><link>http://www.cppblog.com/dbsky/articles/9338.html</link><dc:creator>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </dc:creator><author>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </author><pubDate>Mon, 03 Jul 2006 12:15:00 GMT</pubDate><guid>http://www.cppblog.com/dbsky/articles/9338.html</guid><wfw:comment>http://www.cppblog.com/dbsky/comments/9338.html</wfw:comment><comments>http://www.cppblog.com/dbsky/articles/9338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dbsky/comments/commentRss/9338.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dbsky/services/trackbacks/9338.html</trackback:ping><description><![CDATA[
		<p>DBMS :Database Management System<br />数据模型:概念数据模型 ----设计<br />         逻辑数据模型（关系数据模型，网状数据模型，层次数据模型，）----实现<br />         物理数据模型 <br />数据模式：描述</p>
		<p>联系，约束并发控制：多用户访问共享数据的冲突问题<br /><br />实体—联系：er模型<br /><br />rdbms (关系数据库)     :  sql server ,oracle ,db/2,sybase,informix<br />Non-rdbms (file-based) :  foxpro,access</p>
		<p>客户端网络实用工具(Client Network Utility)：用来配置客户端的网络连接，管理和测定客户端的数据库。</p>
		<p>事件探察器：监视事件处理日志，并对日志进行分析和重播。</p>
		<p>服务端网络实用工具(Server Network Utility):配置服务器端网络连接和设置相关参数。</p>
		<p>导入和导出数据(Imput and Export Data):采用DTC(data transformation services)向导来完成，实现其他数据和SQL 2000数据的转换。</p>
		<p>企业版:win2000 advanced server<br />标准版:win2000 server</p>
		<p>首要数据文件 .mdf<br />次要数据文件 .ndf<br />日志文件     .ldf</p>
		<p>windows身份验证模式 比 混合模式具有更高的安全性，windows身份验证模式下必须是本地用户和域用户才能使用SQL Server 2000</p>
		<p>升级SQL SERVER:备份(包括系统库在内的)所有数据库，备份注册表</p>
		<p>日志文件：<br />sqlstp.log   在\windows或\winnt下<br />setup.log    在\windows或\winnt下<br />searchsetup.log  在\winnt\temp下<br />errorlog     在mssql\log下</p>
		<p>系统数据库：<br />master:<br />model:  是用户数据库和tempdb数据库的摸板数据库，是创建新数据库的摸板<br />msdb:   是代理服务数据库<br />tempdb: 临时数据库，默认大小8mb，为临时操作提供存储空间<br />pubs:   示范学习</p>
		<p>系统表：<br />(<br />sysobjects表<br />syscolumns表<br />sysindexes表<br />sysusers表<br />sysdatabases表<br />sysdepends表<br />sysconstraints表<br />)</p>
		<p>(主关键字(主键)：<br />候选关键字：<br />公共关键字：<br />外关键字：确定主表和从表)</p>
		<p>数据库对象：<br />(<br />表<br />索引<br />视图：其实是虚表，是查询表产生的<br />图表：是表之间的关系示意图<br />确省值：<br />规则：<br />触发器：<br />存储过程：<br />用户：<br />)</p>
		<p>范式：构造数据库必须遵守的规则，目前关系数据库有6种范式，第一范式(1NF)....，一般需要满足3NF</p>
		<p>SQL(structured query language)结构化查询语言</p>
		<p>9种语句<br />(<br />数据查询：select<br />数据定义：create,drop(删除),alter(修改)<br />数据操作：insert,update,delete<br />数据控制：grant,revoke<br />)</p>
		<p>SQL语言分类：<br />(<br />数据定义语言(dll),用于定义数据结构<br />数据控制语言(dml)，用于检索和修改数据结构<br />数据控制语言(dcl),用于规定数据库用户的权限<br />数据库事务处理，用来保证数据库的完整性<br />)</p>
		<p>常用dll语句：<br />(<br />create table<br />create index<br />drop table    删除数据库表<br />drop index<br />truncate      删除表中所有的行<br />alter table   增加表列，重定义表列，更改存储分配<br />alter table add constraint   在已有的表上增加约束<br />)</p>
		<p>常用dml语句:<br />(<br />insert<br />delete<br />update<br />selete<br />)</p>
		<p>常用dcl语句:<br />(<br />grant  将权限或角色授予用户或其他角色<br />revoke 从用户或数据库角色回收权限<br />set role  禁止或允许角色<br />)</p>
		<p>事务处理语句：<br />(<br />commit work  把当前事务所作的更改永久化<br />rollback     作废上次提交以来的所有更改<br />)</p>
		<p>数据表名称 as 数据表别名，如果已经给表定了别名，在T-SQL语句中应引用别名，而不能用数据表名<br />select e.id,e.name from 用户表 as e</p>
		<p>
				<br />select [all | distinct] [top n] selectlist [into[NewtAbleName]]  //distinct:无重复的,selectlist:可以是表达式<br />  from {TableName | ViewName,....}<br />where  conditions<br />[group by group_by_list]  // 分组  <br />[having conditions]       // 分组条件<br />[order by order_by_list [asc | desc]]</p>
		<p>select cost*quantity as sum</p>
		<p>select 数据表 join on (员工数据表.员工编号=项目数据表.负责人)     //联接条件</p>
		<p>嵌套select:<br />select table1.a,tmptable.b<br />from table1,<br />(select table2.c,table2.d<br />from table2<br />where table2.id&gt;2) as tmptable<br />where table1.id=tmptable.id</p>
		<p>
				<br />where:<br />比较：&lt;,&lt;=,&gt;,&gt;=,=,!=,!&lt;,!&gt;<br />范围：between a and b , not between a and b<br />可选择：in,not in <br />模式匹配：like，not like<br />是否空值：is null,is not null<br />逻辑：and,or,not</p>
		<p>like通配符：<br />%  ： like 'wang%'    like '%yi'   <br />-  ： like '_angyi'    <br />[]  ：like '[a-z]angyi'<br />[~] ：like '[~w]angyi'</p>
		<p>in的用例：<br />select name <br />  from table <br />where id in ('4','20')</p>
		<p>escape的用例：<br />select * <br />  from table <br />like 'wang#_yi' escape '#'</p>
		<p>select id,count(*)<br />  from table<br />where wage&gt;=6000<br />group by id</p>
		<p>//group by 对查询结果分组<br />select id,name<br />  from table<br />where level='2'<br />group by id,name     //先按id分，在按name分<br />with cube            //对group产生的组再按组统计<br />with rollup          //只返回第一个分组条件下的再按组统计</p>
		<p>having 指定分组搜索条件，通常与group by一起用<br />having count(*)&gt;1</p>
		<p>select *<br />  from table<br />where col like '%50[%]%'  返回包含50%的字符串</p>
		<p>asc:升续</p>
		<p>//compute计算  avg,sum,min,max,count (都会忽律null)<br />select id,wage <br />   from table<br />order by 部门<br />compute sum(wage) by 部门</p>
		<p>
				<br />count(distinct 列名)</p>
		<p>union</p>
		<p>子查询中一般不用Order by子句，Order by子句用于最终的结果</p>
		<p>&gt;all,&lt;all,<br />&lt;&gt;all等价于not in<br />&gt;some,&lt;some<br />=some 等价于in  &lt;&gt;some等价于 not in</p>
		<p>不要把If..exists和聚合函数一起使用<br /></p>
		<p>数据完整性：<br />实体完整性---表中数据的唯一性<br />区域完整性---字段数据范围的完整性<br />参考完整性----表与表之间关联的完整性<br /><br />使用者定义的完整性----用户自己定义的完整性。如：客户欠6个月的钱，下次再下定单的时候就不卖给他。<br /><br />数据库分离：使用SQL语句分离为EXEC sp_detach_db ‘销售数据库’?指明欲分离的数据库名称即可。分离后想再用该数据库，则需要附加该数据库，具体SQL语句为：<br />CREATE  DATABASE 销售数据库 ON PRIMARY（FILENAME=’C:\SQLTEST\销售数据文件_1。MDF’）<br />FOR  ATTACH 或者使用sp_attach_db系统存储过程来附加数据库：<br />sp_attach_db  销售数据库<br />‘C:\SQLTEST\销售数据文件_1.MDF’</p>
		<p> UNIQUE 和Primary key的差异<br />1、  UNIQUE允许输入NULL值（最多为一个），而Primary key不允许；<br />2、  一个数据表中可以定义多个UNIQUE条件约束，但只能定义一个Primary key条件约束。<br /><br />CHECK约束可用来限制字段值是否在所允许的范围内，例如：<br />CREATE TABLE 客户02<br />(<br />客户编号 int IDENTITY  NULL  UNIQUE,<br />身份证号 char[10] NOT NULL  UNIQUE,<br />年龄  int  CHECK (年龄&gt;0) DEFAULT 2<br />)</p>
		<p>建立计算列：<br />CREATE TABLE 估价<br />(<br />编号  int  IDENTITY,               //自动编号<br />单价  numeric(5,1),<br />数量  int,<br />总价  AS 单价*数量<br />)<br />insert 估价 values(21.5,8)<br />insert 估价 values(12,3)<br />delete from 估价 where 编号=5 or 编号=6<br />drop table 估价<br /><br />创建约束字段：<br />Create table 客户<br />{<br />客户编号  int  IDENTITY  Primary Key,------------------------IDENTITY自动产生编号<br />身份证号  char 18  NOT NULL UNIQUE,<br />地址      char(50),<br />电话      char (12),<br />杂志编号  int  REFERENCES 杂志种类（杂志编号）,<br />订单编号  int  NOT NULL,FOREIGN Key(杂志编号，订户编号)<br />REFERENCES  杂志订户（杂志编号，订户编号），<br />Check(地址 is NOT NULL  OR 电话  is  NOT NULL)<br />}</p>
		<p>修改数据表：<br />ALTER TABLE 客户A<br />ADD<br />类别编号 int <br />DEFAULT 1 WITH VALUES<br />CONSTRAINT  FK_类型编号<br />FOREIGN KEY<br />REFERENCES  客户类别（类别编号）</p>
		<p>删除约束字段：<br />ALTER TABAL订购项目A<br />DROP CONSTRAINT PK_订购项目A<br />下面删除订购项目A的两个字段<br />ALTER TABLE 订购项目A<br />DROP COLUMN 定单编号，项目编号<br /><br />激活/关闭约束<br />ALTER TABLE table<br />{ CHECK | NOCHECK} CONSTRAINT<br />{ALL | constrant_name{,…….n}}</p>
		<p>临时数据表以#或##开头，用户断开连接后表被自动删除</p>
		<p>数据表中字段的种类：<br />Primary key,  Foreign Key,  NULL,  NOT NULL,  DEFAULT,  UNIQUE,  CHECK</p>
		<p>用查询结果建立新数据表<br />Select * into  newtablename  from table_source where 条件</p>
		<p>重复记录采用DISTINCT来获取单独的数据。</p>
		<p>TOP  N 为显示前N个数据，TOP  N  30  PERSENT * FROM 表名</p>
		<p>表示显示N的前30%的数据</p>
		<p> ORDER BY 按什么方式排序显示结果，ASC升DESC降</p>
		<p> JOIN ：SELECT  A,B,C  FROM  T1  JOIN  T2  ON  T1.NO=T2.NO</p>
		<p>JOIN 的类型有多种：INNER（默认）LEFT（以左边为条件，如果右边没有符合的条件，则以NULL）<br />        SELECT 旗.产品名称AS旗旗公司产品名称，旗.价格，标.成品名称AS标标公司产品名称，标.价格 FROM 旗旗公司 AS 旗 LEFT JOIN 标标公司AS标 ON旗.产品名称=标产品名称 RIGHT（以右边为条件，如果左边没有符合的条件，则以NULL）FULL（左边右边都显示，如果没有则以NULL） CROSS（将两个表的数据进行比较，全部显示出来）</p>
		<p>有时需要自己JOIN自己<br />SELECT 员工.姓名，员工.职位，长官.姓名AS主管 <br />FROM 员工 LEFT JOIN 员工AS 长官<br />ON 员工.主管编号=主管.编号 姓名 职位 主管<br /> 1<br /> a<br /> b<br /> c<br /> 2<br /> d <br />e <br />NULL<br /><br />GROUP BY 按什么分组显示<br /><br />UNION把两个查询结果合并到一个表中显示出来查询时Group的使用， <br />Select name  AS名称,Sum(Quantity)数量  Form  table  Group  By  name<br /><br />GROUP BY后面如果有WITH CUBE则把各个组进行汇总计算后显示结果 </p>
		<p>查询：select name  AS出版社名称,bookname AS 书名,sum(quantity) AS 数量 from table group by name,bookname with cube</p>
		<p>查询时改变要显示的数据：（1代表“男”，0代表“女”）要求查询时如果是1则显示“男”，否则显示“女”</p>
		<p>Select name  AS 姓名,case  sex  when  0  then “女” else  “男”  End  AS 性别  From  table</p>
		<p> 比较清单有：IN，ALL，ANY（SOME）结果为TRUE或FALSE<br /><br />测试存在用EXISTS结果返回TRUE，FALSE</p>
		<p> 索引分为聚集索引和非聚集索引</p>
		<p>聚焦索引数据的存放会依照该索引的顺序来存放</p>
		<p>非聚焦索引数据的存放不会依照索引的顺序来存放</p>
		<p>因为非聚焦索引不影响数据排列顺序，则可以设置多个非聚焦索引，而聚焦索引则最多只能设置一个，因为实际数据只能有一种排列顺序。</p>
		<p>(Unique index)索引值是否唯一：如果索引值为唯一，则成为唯一索引</p>
		<p>多个字段做为索引称为复合索引（Composite index）</p>
		<p>Create  [UNIQUE]  -----指定唯一<br />CREATE  TABLE  t<br />(<br />ProductID  smallint  not null  primary key,<br />ProductName   char(30),<br />Price   smallmoney,<br />Manufacturer   char(30)<br />)         <br />//创建索引<br />CREATE  UNIQUE   NONCLUSTERED    INDEX    indexname<br />ON   t (Price   DESC)<br />WITH     PAD_INDEX, FILLFACTOR=30,IGNORE_DUP_KEY<br /><br />//删除索引<br />DROP  INDEX   table.index_name<br /><br />//修改索引<br /><br />使用DROP_EXISTING修改索引,如果要修改索引，只要在CREATE    INDEX语句的最后加上DROP_EXISTING即可（如果存在该索引，则修改之，否则会发生错误）</p>
		<p>使用DBCC  DBREINDEX重建索引</p>
		<p>如果只想重建索引（而不修改索引的相关设置），那么使用DBCC  DBREINDEX语句比较方便，而且使用时也可指定重建的填充因子。</p>
		<p>DBCC DBREINDEX（’database_name.owner.table_name’,  index_name,   fillfactor）数据库  数据库所有者 表名  重建的索引名 设置新的填充因子[WITH  NO_INFOMSGS]   -------有此项，则重建索引不会显示出信息 </p>
		<p> 存储过程<br />系统存储过程都是以 sp_开头<br />扩展存储过程通常以xp_开头<br />EXECUTE 执行存储过程或SQL字符串（EXEC）<br />EXEC  存储过程名   参数1   参数2   参数3……</p>
		<p> 变量的声明：<br />DECLARE  @A  int -------------- 生命了一个为int 类型的A 变量。</p>
		<p>建立存储过程<br />使用CREATE  PROC或者CREATE  PROCEDURE + 过程名 + AS +SQL语句<br />CREATE  PROC  MyProcl<br />AS  SELECT * FROM 标标公司  WHERE 价格 &gt;5<br />GO<br />EXEC MyProcl</p>
		<p>EXEC  lookup  ‘杨小雄’，@地址 OUTPUT---OUTPUT表示参数的值是可以返回的</p>
		<p>一个存储过程为一个批，因此在查询分析器中遇到GO时，表示存储过程的定义已结束.在存储过程中,有些创建对象的语句不可使用<br />CREATE  DEFAULT       CREATE  TRIGGER<br />CREATE  PROCEDURE    CREATE  VIEW<br />CREATE  RULE</p>
		<p>临时存储过程分为局部和全局<br />局部要以#开头<br />全局要以##开头</p>
		<p>修改存储过程ALTER PROC<br />删除存储过程DROP PROC</p>
		<p>建立函数CREATE  FUNCTION                     <br />修改函数 ALTER  FUNCTION             <br />删除函数DROP  FUNCTION</p>
		<p>返回单个数据的函数和一般函数一样<br />返回大量数据集的函数如下例：<br />CREATE FUNCTION 依售价查询书籍<br />（@由 money,  @到money）<br />RETURNS TABLE<br />RETURN  （SELECT 书籍编号，书籍名称，单价 FROM 书籍 WHERE 单价&gt;=@由AND单价&lt;=@到）<br />GO</p>
		<p>SELECT * FROM依售价查询书籍（400，500）<br />ORDER  BY  单价<br />在调用系统内置的函数时，需要加上   ：：如：SELECT * FROM ：：fn_helpcollations()在创建表时可以使用这些函数。</p>
		<p> 函数分为确定性函数和非确定性函数<br />确定性函数为当传入的参数不变时，返回值不变，而非确定性函数为传入参数不变，但每次返回的值会改变（如：GETDATE（）函数）</p>
		<p> 触发器（Trigger）是一种与数据表紧密结合的存储过程，当该数据表有新建（INSERT）更改（UPDATE）或删除（DELETE）事件发生时，所设置的触发器会自动被执行，以进行数据完整性，或其他一些特殊的数据处理工作。</p>
		<p>触发器是针对单一数据表所撰写的特殊存储过程。触发器的种类与操作：触发器分为2类<br />AFTER触发器：这类触发器要在数据已变动完成之后（AFTER），才会被激活并进行必要的善后处理或检查。若发现错误，则可用ROLLBACK  TRANSATION回滚全部数据。<br />INSTEAD  OF触发器：INSTEAD  OF 是取代的意思，就是这类触发器会取代原本要进行的操作（例如新建或更改数据库操作），因此会在数据变动前就发生，而且数据要如何变动也完全取决于触发器。（该触发器能应用与数据表与视图）</p>
		<p>建立触发器<br />CREATE  TRIGGER  trigger_name<br />ON  {table|view}<br />[with  encryption]        ------加密<br />{FOR|AFTER|INSTEAD OF}  ------FOR和AFITER都是要等到数据完全操作完后才激活触发器，INSTEAD OF则表示要建立INSTEAD OF触发器，此时触发器将取代原来要执行的数据操作。<br />{[DELETE][,][INSERT][,][UPDATE]}-----指定触发器的触发操作，必须指定一个，多个时以逗号隔开，在同一数据表中，AFTER触发器数目没有限制；但对INSTEAD OF 触发器来说则限制DELETE、INSERT、UPDATE每项最多只能有一个。<br />AS<br /><br />Sql_statements    ------用来定义触发器的内容。</p>
		<p>例如：下面对一个表建立2个触发器：<br />CREATE  TRIGGER  订单修改通知<br />ON  订单<br />AFTER  INSERT ，UPDATE<br />AS<br />PRINT  ‘又有订单被修改了！’<br />GO</p>
		<p>
				<br />CREATE TRGGER 订单删除通知<br />ON  订单<br />AFTER  DELETE<br />AS<br />PRINT  ‘又有订单被删除了！’<br />GO<br /><br />INSERT 订单(日期，客户编号)<br />Values(‘2000/1/1’,3)<br />Delete订单<br />Where 日期=‘2000/1/1’</p>
		<p> 删除触发器：DROP  TRIGGER  trigger_name</p>
		<p> 事务通常是由BEGIN  TRAN 语句开始，一直执行到COMMIT  TRAN或ROLLBACK  TRAN语句时才结束。</p>
		<p>当执行完事务中的最后一项数据库的操作后，若没有任何错误，我们可以用COMMIT TRAN提交事务。反之，若发现在事务中有任何的错误，则执行ROLLBACK  TRAN取消事务，并回滚至事务执行前的状态。</p>
		<p>每执行完一项数据库的操作后，要立即检查@@ERROR和@@ROWCOUNT，否则再执行下一项数据库操作时，这2个系统变量将会被新的值代替。在更改或删除数据时，若因指定条件不符或其他原因而没有更改到任何一条记录，由于这种情况并不是错误（@@ERROR仍为0），因此我们还要检查@@ROWCOUNT的更改条数，以确定数据已正确更改。</p>
		<p> 无论是COMMIT TRAN还是ROLLBACK TRAN而结束的事务后，如果后面还有其他未执行的语句，则还会继续执行这些语句，直到批结束。不过已COMMIT的事务就无法再ROLLBACK了，同理，已ROLLBACK的事务也无法再COMMIT了。</p>
		<p> 在事务中，把事务中所有的语句看成是一个数据处理单元，因此单元必须全部做完或全部不做。</p>
		<p> 事务的4大特性：<br />1，  原子性：整个事务被看成一个执行单元，要么全部成功，要么全部取消。<br />2，  一致性：当事务完成后，数据库的内容必须全部更新妥当，而且仍然具备正确性及完整性。<br />3，  隔离性：在事务中所使用到的数据，必须与其他同时在进行的事务适度隔离（使用锁定数据的方法来隔离事务）<br />4，  永久性：事务一旦提交后，其所作的数据修改将被视为永久性的，无法再用ROLLBACK回滚了。</p>
		<p>
				<br />事务是以连接为单位，每个连接都可以有自己的事务。<br />事务的执行有3种模式：<br />1，  外显事务2，  自动提交事务3，  隐含事务</p>
		<p>嵌套事务是以最外层的事务为提交或回滚对象的。<br />虽然嵌套事务是以最外层为提交对象的，但其中的每个事务都有自己的BEGIN TRAN 和COMMIT<br />其实事务是为存储过程而设计的，因为这样我们就可以在存储过程中撰写事务程序，而不用担心该程序被调用时是否已在另一个事务之中。</p>
		<p> @@TRANCOUNT事务计数<br />无论是那里调用ROLLBACK，都会跳转到最外层的BEGIN TRAN处，@@TRANCOUNT都会变为0。‘<br />有时在事务中发生错误时，我们希望只要回滚一小部分就可以了<br />则用SAVE TRANSACTION来设置“事务保存点”，然后在必要时使用ROLLBACK来回滚到所保存的位置，而不会中断事务。<br /><br />ROLLBACK 后的事务名称只能是由SAVATRAN或最外层的BEGIN TRAN所声明的事务名称。</p>
		<p>游标的状态：<br />1<br /> Cursor已打开，其内有0，1或多条记录<br /> 0<br /> Cursor已打开，但确定其内没有查询到任何一条信息记录<br /> -1<br /> Cursor已关闭<br /> -2<br /> Cursor变量名未参照到时间Cursor或参照的Cursor已被DeAllocale<br /> -3<br /> 指定的游标变量名不存在<br /> <br />Cursor主要是使用于SQL批、存储过程和出发器中。<br />游标的格式：<br />DECLARE  游标名  CURSOR  -------声明游标<br />FOR  SELECT 姓名  FROM 通讯薄  WHERE 地址=台北    -------------游标的数据来源<br />OPEN 游标名   -----------打开游标<br />DECLARE  @name  varchar(20)<br />FETCH  NEXT  FROM  游标名     ------------将第一条数据存入@name<br />INTO  @name<br />WHILE(@@FETCH_STATUS=0)      -------------判断是否读到数据，0表示读到数据<br />BEGIN<br />   FETCH  NEXT  FROM 游标名<br />   INTO  @name<br />END<br />CLOSE  游标名   ----------------关闭游标与数据的关联<br />DEALLOCATE  游标名  ---------------将游标对象删除<br />除了Cursor中FETCH数据外，可以通过Cursor来UPDATE或DELETE一条目前所指定的记录</p>
		<p>UPDATE 标标公司   SET 价格=100  WHERE CURRENT  OF  游标名<br />DELETE 标标公司   WHERE CURRENT  OF  游标名</p>
		<p>范例：<br />DECLARE  MyCursor  CURSORLOCAL   SCROLL_LOCKS<br />FOR  SELECT 价格FROM  标标公司<br />FOR  UPDATE<br />OPEN  MyCursor<br />DECLARE  @money   money<br />FETCH  MyCursor  INTO @money<br />WHILE(@@FETCH_STATUS=0)<br />BEGIN<br />    IF  @money&lt;=10<br />      BEGIN<br />         SET @money=money*1.1<br />               UPDATE  标标公司<br />               SET 价格<a href="mailto:=@money">=@money</a>               -----------------更新价格信息<br />               WHERE   CURRENT OF MyCursor<br />       END<br />FETCH  MyCursor  INTO @money<br />END</p>
		<p>游标变量，使用SET将已经声明好的游标给游标变量。在使用上，游标变量和游标是一样使用的<br /><br />全局游标和本地游标有相同的变量时，以本地游标为优先调用</p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br /> </p>
<img src ="http://www.cppblog.com/dbsky/aggbug/9338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dbsky/" target="_blank"><FONT color=red>dbsky </FONT> </a> 2006-07-03 20:15 <a href="http://www.cppblog.com/dbsky/articles/9338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于ODBC的读书笔记</title><link>http://www.cppblog.com/dbsky/articles/9332.html</link><dc:creator>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </dc:creator><author>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </author><pubDate>Mon, 03 Jul 2006 11:23:00 GMT</pubDate><guid>http://www.cppblog.com/dbsky/articles/9332.html</guid><wfw:comment>http://www.cppblog.com/dbsky/comments/9332.html</wfw:comment><comments>http://www.cppblog.com/dbsky/articles/9332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dbsky/comments/commentRss/9332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dbsky/services/trackbacks/9332.html</trackback:ping><description><![CDATA[
		<p>ODBC(Open Database Connectivity)   Connectivity:连通性<br />DSN（Data Source Name）用于指定ODBC与相关的驱动程序相对应的一个入口<br />当应用程序要使用ODBC访问数据库时，就需要指定一个DSN以便于连接到一个指定的ODBC驱动程序</p>
		<p>ATL(Active样板库)<br />UDA通用数据访问，使用OLE DB访问任何数据库 由OLE DB,ADO,ODBC组成<br />RDO远程数据对象<br />DAO数据访问对象<br />ODBC开放数据库互连<br />ADO(Active Data Object)是一个访问OLE DB的类层<br />OLE DB有一组COM接口组成</p>
		<p>ODBC的框架<br />1。使用驱动器管理器和特定的数据库驱动器来获得ODBC,<br />2。利用ODBC来调用应用程序，访问ODBC驱动器管理器(ODBC32DLL)，<br />3。利用ODBC驱动器管理器调用数据库指定的ODBC驱动器，<br />4。利用数据库指定的ODBC驱动器来访问数据库</p>
		<p>ODBC访问多种数据库<br />                                                                            |-&gt;Oracle ODBC数据库驱动器<br />ODBC应用程序--&gt;ODBC驱动器管理程序--&gt;|                             --&gt;关系数据库数据源<br />                                                                            |-&gt;SQL Server数据库驱动器</p>
		<p>CObject类 CDatabase CRecordset访问数据库源</p>
		<p>
				<br />DSN共分为三类：<br />用户DSN：对当前登录用户可见，只能够用于当前计算机。<br />系统DSN：对当前系统上所有用户可见，包括NT中的服务。<br />文件DSN：DSN信息存放在文件中，对能够访问到该文件的用户可见。</p>
		<p>一个使用Access数据库的DSN中的信息如下：<br />[ODBC]<br />DRIVER=Driver do Microsoft Access (*.mdb)<br />UID=Admin<br />DefaultDir=C:\DB<br />DBQ=C:\DB\1.mdb</p>
		<p>在使用ODBC开发时一个重要的问题就是数据转换的问题,在程序运行过程中数据需要经历两次转换：C语言的数据或结构类型与ODBC的数据类型的转换，ODBC与SQL间数据类型的转换</p>
		<p>ODBC中的句柄分为三类：环境句柄，数据库连接句柄，SQL语句句柄<br /></p>
<img src ="http://www.cppblog.com/dbsky/aggbug/9332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dbsky/" target="_blank"><FONT color=red>dbsky </FONT> </a> 2006-07-03 19:23 <a href="http://www.cppblog.com/dbsky/articles/9332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动态创建MSSQL的DSN</title><link>http://www.cppblog.com/dbsky/articles/9330.html</link><dc:creator>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </dc:creator><author>&lt;FONT color=red&gt;dbsky &lt;/FONT&gt; </author><pubDate>Mon, 03 Jul 2006 11:18:00 GMT</pubDate><guid>http://www.cppblog.com/dbsky/articles/9330.html</guid><wfw:comment>http://www.cppblog.com/dbsky/comments/9330.html</wfw:comment><comments>http://www.cppblog.com/dbsky/articles/9330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dbsky/comments/commentRss/9330.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dbsky/services/trackbacks/9330.html</trackback:ping><description><![CDATA[
		<font color="#000080">代码如下</font>：<br />if(SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN,"SQL Server","DSN=TestDB\0Description=TestAPIODBC\0SERVER=(local)\0DATABASE=TestDB"))<br /> {<br />  printf("32位ODBC数据源配置 Success!\n\n");<br /> }<img src ="http://www.cppblog.com/dbsky/aggbug/9330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dbsky/" target="_blank"><FONT color=red>dbsky </FONT> </a> 2006-07-03 19:18 <a href="http://www.cppblog.com/dbsky/articles/9330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>