当前位置:  数据库>sqlserver
本页文章导读:
    ▪学会使用ODBC API      学会使用ODBC API  虽说以前也接触过一些数据库的应用,但是由于当时只是抱着非常浅显的数据库知识,做了一些SQL语句上的操作,安装-配置-连接这一系列的流程全是自己照着例子实现的.........
    ▪SQL2005隐藏服务器的方法      SQL2005隐藏服务器的方法在SQL2000里的网络实用工具里有一个选项:隐藏服务器,这样当你枚举局域网中的SQL2000服务器的时候就会搜索不了以为SQL2005没有了这个功能,今晚发现原来在配置管理.........
    ▪SQL执行顺序      SQL 不同于与其他编程语言的最明显特征是处理代码的顺序。在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几.........

[1]学会使用ODBC API
    来源:    发布时间: 2013-10-15

学会使用ODBC API

  虽说以前也接触过一些数据库的应用,但是由于当时只是抱着非常浅显的数据库知识,做了一些SQL语句上的操作,安装-配置-连接这一系列的流程全是自己照着例子实现的,大概记住的也就是ODBC、ADO之类,也简单的理解了一下,当共享使用数据库时最好使用ODBC的方式,而本地的数据库就可以使用ADO。

  具体区别这些连接方式倒是就可以好好学习一下了:

  • MDAC:http://zh.wikipedia.org/wiki/MDAC
  • ODBC:http://zh.wikipedia.org/zh-cn/ODBC
  • ADO:http://zh.wikipedia.org/wiki/ADO

  简单的来说,ODBC和ADO都是微软提供的数据库访问方式,ADO是一个COM组件,而ODBC则是一种标准的访问方式,结束了数据库访问和数据库相关的局面,只不过两者实现的不同,所以在不同应用的表象上不同罢了(不对的话请指出,只看了Wiki上的一点介绍,没有系统学习)。

使用

  通过分析考虑到将来可能会采用共享数据库的方式,此外对于COM自己也不是很熟悉,所以还是使用ODBC的方式比较好,使用ODBC的方式就很多了,但是由于我并不是程序开发人员,现在负责维护,不大敢做大手术,所以就选择了ODBC API,这就相当于使用WINDOS API和MFC一样,虽然API复杂,但是相对自由很多。

  首先要在程序中添加几个依赖项

#include <sql.h>
#include <sqlext.h>
#include <odbcinst.h>

#pragma comment(lib,"odbc32.lib")
#pragma comment(lib,"odbccp32.lib")

  前两个头文件分别代表基本的ODBC API和高级的ODBC API,最后一个好像是包含了更高级的API(暂时这么理解吧),一般用到前两个即可,odbc32.lib对应sql.h和sqlext.h,odbccp32.lib对应odbcinst.h。

  所有使用数据库的过程无非是这样一个流程:

  1. 想办法建立数据库的连接

  2. 想办法执行SQL语句,并使用结果

  3. 不用时关闭连接,以免下次访问报错

  对于像我这样不常用数据库的菜鸟来说,这样的方式足够完成我所面临的问题了,诸如互斥访问、分布式之类的问题还是暂时留给高手们考虑吧。

建立数据库连接

  在我们要连接数据库的类中,或者全局变量下建立相关的变量

SQLHENV m_hEnviroment;//数据库环境句柄,属于老大级别的
SQLHDBC m_hDatabaseConnection;//数据库连接句柄,老大以后就是他了,有了他数据库就连接上了
SQLHSTMT m_hStatement;//执行语句句柄,最终执行SQL于句的句柄

  使用ODBC API建立数据库连接分为3部分:申请环境句柄,使用环境句柄申请连接句柄、使用连接句柄连接数据库。

   /* 申请环境变量 */
SQLRETURN l_uiReturn = SQLAllocHandle(SQL_HANDLE_ENV,NULL,&m_hEnviroment);
  //申请各种句柄都靠这个函数,参数1是要申请句柄的类型,参数2为申请该句柄依靠的句柄(老大没依靠,所以是NULL),申请结果在参数3中保存
  //返回值代表着执行的意义,如下面判断,SUCCESS_WITH_INFO相当于是警告,虽然成功了,但是可能有问题

  if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return false;
}

SQLSetEnvAttr(m_hEnviroment,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);

l_uiReturn = SQLAllocHandle(SQL_HANDLE_DBC,m_hEnviroment,&m_hDatabaseConnection);
if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return false;
}

SQLWCHAR * l_swcaDsnName = _T("");//数据源名称
SQLWCHAR * l_swcaUserName = _T("");//用户名称
SQLWCHAR * l_swcaPassWord = _T("");//密码

l_uiReturn = SQLConnect(m_hDatabaseConnection,l_swcaDsnName,SQL_NTS
,l_swcaUserName,SQL_NTS
,l_swcaPassWord,SQL_NTS);

if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return false;
}

使用SQL语句

/* 申请于句句柄 */
SQLRETURN l_uiReturn = SQLAllocHandle(SQL_HANDLE_STMT,m_hDatabaseConnection,&m_hStatement);
if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return 0;
}

/* 构造SQL语句 */
CString l_cstrSql;
l_cstrSql.Format(_T("SELECT * FROM 数据表 "));

/* 执行SQL语句 */
l_uiReturn = SQLExecDirect(m_hStatement,l_cstrSql.GetBuffer(),SQL_NTS);

if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return 0;
}

/* 获得返回结果的行数 */
SQLINTEGER l_siIdCount = 0;
l_uiReturn = SQLRowCount(m_hStatement,&l_siIdCount);

/* 开始读取结果 *///读取第一行时要调用,以后依次调用就可以下移行数,直到不返回SQL_SUCCESS
l_uiReturn = SQLFetch(m_hStatement);

if (l_uiReturn != SQL_SUCCESS && l_uiReturn != SQL_SUCCESS_WITH_INFO)
{
return 0;
}

SQLINTEGER l_siID;
SQLINTEGER l_siIDLength = 0;

/* 获得数据 */
SQLGetData(m_hStatement,1,SQL_C_ULONG,&l_siID,0,&l_siIDLength);
//参数1为执行语句的句柄,参数2为所要得到的数据位于的列数(SQL语句中),参数3为数据类型,这个比较多,需要看一下MSDN
//参数4为保存的位置(地址),参数5为参数4可用的位置,既然参数3已设定为长整型,所以这里可使用0
//参数6为实际返回的长度

/* 释放语句句柄 */
SQLFreeHandle(SQL_HANDLE_STMT,m_hStatement);

断开连接

SQLFreeHandle(SQL_HANDLE_STMT,m_hStatement);
SQLFreeHandle(SQL_HANDLE_DBC,m_hDatabaseConnection);
SQLFreeHandle(SQL_HANDLE_ENV,m_hEnviroment);

 

后记:客户需求与实现方式的思考  

  客户来了新的需求-交换:当时的原型为,他们那里有一套嵌入式的系统负责从传感器上获得数据,他们也有一套相应的管理程序,但是但是那套管理程序缺乏显示效果,所以需要利用我们所做的系统进行显示。

  根据这个需求,我们(其实只有我一个人)进行了分析,当时客户提出的最好使用SOCKET变成来实现,按说这也是一个不错的主意,自由且不是很复杂,但是带来的后果就可能是以后如果各种交互多了以后,极难维护。所以觉得使用一个共同的数据库比较好,他们负责生成数据,我们负责读取并显示,这种好处是可以最大的运用程序的效率,不用总是考虑SOCKET能不能及时的接收到,而且责任分明,也方便维护,但是现在考虑这种方式的缺点就是,我们的代码有一定的重复,他们的客户端就有一些根据数据条件进行“分类”的意思,我们这边则要根据数据进行不同的显示效果。

本文链接


    
[2]SQL2005隐藏服务器的方法
    来源:    发布时间: 2013-10-15
SQL2005隐藏服务器的方法

在SQL2000里的网络实用工具里有一个选项:隐藏服务器,这样当你枚举局域网中的SQL2000服务器的时候就会搜索不了

以为SQL2005没有了这个功能,今晚发现原来在配置管理器里

大家看下面几张图就晓得步骤了,设置完毕之后需要重启SQL服务哦o(∩_∩)o 

SQL2000的

SQL2005的

 

 

设置了隐藏实例之后就搜索不了

不隐藏实例

 

本文链接


    
[3]SQL执行顺序
    来源:    发布时间: 2013-10-15

SQL 不同于与其他编程语言的最明显特征是处理代码的顺序。在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几乎总是最后被处理。

      每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回 给调用者。如果没有在查询中指定某一子句,将跳过相应的步骤。下面是对应用于SQL server 2000和SQL Server 2005的各个逻辑步骤的简单描述。 

(8)SELECT (9)DISTINCT (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>

逻辑查询处理阶段简介

  • FROM:对FROM子句中的前两个表执行笛卡尔积(Cartesian product)(交叉联接),生成虚拟表VT1
  • ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。
  • OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
  • WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
  • GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.
  • CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
  • HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会被插入VT7.
  • SELECT:处理SELECT列表,产生VT8.
  • DISTINCT:将重复的行从VT8中移除,产生VT9.
  • ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).
  • TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者。
  • 注:步骤10,按ORDER BY子句中的列列表排序上步返回的行,返回游标VC10.这一步是第一步也是唯一一步可以使用SELECT列表中的列别名的步骤。这一步不同于其它步骤的 是,它不返回有效的表,而是返回一个游标。SQL是基于集合理论的。集合不会预先对它的行排序,它只是成员的逻辑集合,成员的顺序无关紧要。对表进行排序 的查询可以返回一个对象,包含按特定物理顺序组织的行。ANSI把这种对象称为游标。理解这一步是正确理解SQL的基础。

    因为这一步不返回表(而是返回游标),使用了ORDER BY子句的查询不能用作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和共用表达式。它的结果必须返回给期望得到物理记录的客户端应用程序。例如,下面的派生表查询无效,并产生一个错误:

    select *
    from(select orderid,customerid from orders order by orderid)
    as d

    下面的视图也会产生错误

    create view my_view
    as
    select *
    from orders
    order by orderid

          在SQL中,表表达式中不允许使用带有ORDER BY子句的查询,而在T—SQL中却有一个例外(应用TOP选项)。

          所以要记住,不要为表中的行假设任何特定的顺序。换句话说,除非你确定要有序行,否则不要指定ORDER BY 子句。排序是需要成本的,SQL Server需要执行有序索引扫描或使用排序运行符。

    本文链接


        
    最新技术文章:
    ▪Sql Server里删除数据表中重复记录的例子
    ▪如何查看SQLSERVER中某个查询用了多少TempDB空间...
    ▪在SQL Server中使用ISNULL执行空值判断查询
    ▪揭秘SQL Server 2014有哪些新特性(1)-内存数据库
    ▪揭秘SQL Server 2014有哪些新特性(2)-固态硬盘 Buff...
    ▪揭秘SQL Server 2014有哪些新特性(3)-可更新列存...
    ▪揭秘SQL Server 2014有哪些新特性(4)-原生备份加...
    ▪解决SqlServer 各版本 sa帐户不能登录问题
    ▪浅析SQL Server中包含事务的存储过程
    ▪深入分析MSSQL数据库中事务隔离级别和锁机制
    ▪SQL优化技巧指南
    ▪人工智能自动sql优化工具--SQLTuning for SQL Server
    ▪使用 TOP 子句限制UPDATE 语句更新的数据
    ▪sql server动态存储过程按日期保存数据示例
    ▪SQLServer用存储过程实现插入更新数据示例
    ▪SqlServer中tempdb的日志机制原理解析及示例分享...
    ▪SqlServer数据库提示 “tempdb” 的日志已满 问题...
    ▪浅谈tempdb在SqlServer系统中的重要作用
    ▪SqlServer提示“列前缀tempdb.无效: 未指定表名”...
    ▪SQL命令优化需要记住的9点事项
    ▪教你如何看懂SQL Server查询计划
    ▪sql server 2000数据库备份还原的图文教程
    ▪SqlServer2012中First_Value函数简单分析
    ▪sql语句中单引号嵌套问题(一定要避免直接嵌...
    ▪谈谈sqlserver自定义函数与存储过程的区别
    ▪SQL SERVER使用REPLACE将某一列字段中的某个值替...
    ▪总结一周内学习的Sql经验(一)
    ▪sql存储过程详解
    ▪SQL Server UPDATE语句的用法详解
    ▪MSSQL事务的存储过程
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3