SQL Server 2005新功能-TSQL

 更新时间:2016年11月25日 16:43  点击:1400
SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的。
举几个例子来简单说明 这些例子我引用了Northwind库。
1. TOP 表达式
SQL Server 2000的TOP是个固定值,是不是觉得不爽,现在改进了。
 
--前n名的订单
declare @n int
set @n = 10
select TOP(@n) * from Orders
2. 分页
不知各位过去用SQL Server 2000是怎么分页的,大多都用到了临时表。SQL Server 2005一句话就支持分页,性能据说也非常不错。
 
--按Freight从小到大排序,求20到30行的结果
select * from(
select OrderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from Orders
) a
where row between 20 and 30
3. 排名
select * from(
select OrderId, Freight, RANK() OVER(order by Freight) as rank from Orders
) a
where rank between 20 and 30
4. try ... catch
SQL Server 2000没有异常,T-SQL必须逐行检查错误代码,对于习惯了try catch程序员,2005是不是更加亲切:
SET XACT_ABORT ON -- 打开 try功能
BEGIN TRY
begin tran
insert into Orders(CustomerId) values(-1)
commit tran
print 'commited'
END TRY
BEGIN CATCH
rollback
print 'rolled back'
END CATCH
5. 通用表达式CTE
通过表达式可免除你过去创建临时表的麻烦。
www.111cn.net
--例子:结合通用表达式进行分页
WITH OrderFreight AS(
select OrderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from Orders
)
select OrderId, Freight from OrderFreight where row between 10 and 20
特别,通过表达式还支持递归。
6. 直接发布Web Service
想要把store procedure变成Web Service就用这个吧,.NET, IIS都不需要,通过Windows 2003的HTTP Protocol Stack直接发布WebService,用这个功能需要Windows 2003 sp1
--DataSet CustOrdersOrders(string customerID)
CREATE ENDPOINT Orders_Endpoint
state=started
as http(
path='/sql/orders',
AUTHENTICATION=(INTEGRATED),
SQL注入是什么?
许多网站程序在编写时,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码(一般是在浏览器地址栏进行,通过正常的www端口访问),根据程序返回的结果,获得某些想得知的数据,这就是所谓的SQL Injection,即SQL注入。 
SQL注入通过网页对网站数据库进行修改。它能够直接在数据库中添加具有管理员权限的用户,从而最终获得系统管理员权限。黑客可以利用获得的管理员权限任意获得网站上的文件或者在网页上加挂木马和各种恶意程序,对网站和访问该网站的网友都带来巨大危害。
  防御SQL注入有妙法
  第一步:很多新手从网上下载SQL通用防注入系统的程序,在需要防范注入的页面头部用来防止别人进行手动注入测试。
  可是如果通过SQL注入分析器就可轻松跳过防注入系统并自动分析其注入点。然后只需要几分钟,你的管理员账号及密码就会被分析出来。
  第二步:对于注入分析器的防范,笔者通过实验,发现了一种简单有效的防范方法。首先我们要知道SQL注入分析器是如何工作的。在操作过程中,发现软件并不是冲着“admin”管理员账号去的,而是冲着权限(如flag=1)去的。这样一来,无论你的管理员账号怎么变都无法逃过检测。
  第三步:既然无法逃过检测,那我们就做两个账号,一个是普通的管理员账号,一个是防止注入的账号,为什么这么说呢?笔者想,如果找一个权限最大的账号制造假象,吸引软件的检测,而这个账号里的内容是大于千字以上的中文字符,就会迫使软件对这个账号进行分析的时候进入全负荷状态甚至资源耗尽而死机。下面我们就来修改数据库吧。
  1.对表结构进行修改。将管理员的账号字段的数据类型进行修改,文本型改成最大字段255(其实也够了,如果还想做得再大点,可以选择备注型),密码的字段也进行相同设置。
  2.对表进行修改。设置管理员权限的账号放在ID1,并输入大量中文字符(最好大于100个字)。
  3.把真正的管理员密码放在ID2后的任何一个位置(如放在ID549上)。
  我们通过上面的三步完成了对数据库的修改。
  这时是不是修改结束了呢?其实不然,要明白你做的ID1账号其实也是真正有权限的账号,现在计算机处理速度那么快,要是遇上个一定要将它算出来的软件,这也是不安全的。我想这时大多数人已经想到了办法,对,只要在管理员登录的页面文件中写入字符限制就行了!就算对方使用这个有上千字符的账号密码也会被挡住的,而真正的密码则可以不受限制。
 


PHP在Linux/Unix下连接oracle8是很容易的事,但在windows平台下实在不易,本人经过长久的摸索才找到可靠的方法,不敢独享,
现公布出来以飨大家。
笔者使用的开发环境:
windows 98 第二版
php4.04pl1
apache 1.3.14 window版
oracle 8.05客户端
PHP以CGI方式安装完毕测试成功后。以以下代码测试
<?php
$conn = OCILogon("cinmsiii","cinmsiii","(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.3.202)(PORT = 1521))(CONNECT_DATA = (SID = unicom)))");
//$conn=OCILogon("cinmsiii","cinmsiii","cinms");如果oracle客户端是8.1.6i的话可以这样用,参数照上
if($conn!=false)
{
echo "ok";
OCILogoff($conn);
}
else
echo "false";
?>
关于连接参数问题:
连接串设为以下:
(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.3.202)(PORT = 1521))(CONNECT_DATA = (SID = unicom)))
PROTOCOL:为使用的网络协议
HOST:为数据库服务器主机名
SID:为数据库的实例号
这样作后一般没有任何问题。
如果你的oracle 8客户端为 8.1.6i企业版,可以把这些参数设在连接串中,用 oracle8的net easy config实用工具设置。
将设置后的连接串名称作为连接串传入。
推测oracle 7.x也可以用此方法,因没有环境,未作测试,如果你有兴趣可以试试。

  mysql可通过两种方式通过PHP与web相连,一种通过php的mysql相关函数,另一种通过php的ODBC相关函数
相关函数如下:
MYSQL函数
mysql_affected_rows: 得到 MySQL 最后操作影响的列数目。
 
mysql_close: 关闭 MySQL 伺服器连线。
 
mysql_connect: 开启 MySQL 伺服器连线。
 
mysql_create_db: 建立一个 MySQL 新资料库。
 
mysql_data_seek: 移动内部传回指标。
 
mysql_db_query: 送查询字串 (query) 到 MySQL 资料库。
 
mysql_drop_db: 移除资料库。
 
mysql_errno: 传回错误讯息代码。
 
mysql_error: 传回错误讯息。
 
mysql_fetch_array: 传回阵列资料。
 
mysql_fetch_field: 取得栏位资讯。
 
mysql_fetch_lengths: 传回单列各栏资料最大长度。
 
mysql_fetch_object: 传回物件资料。
 
mysql_fetch_row: 传回单列的各栏位。
 
mysql_field_name: 传回指定栏位的名称。
 
mysql_field_seek: 设定指标到传回值的某栏位。
 
mysql_field_table: 获得目前栏位的资料表 (table) 名称。
 
mysql_field_type: 获得目前栏位的型态。
 
mysql_field_flags: 获得目前栏位的旗标。
 
mysql_field_len: 获得目前栏位的长度。
 
mysql_free_result: 释放传回占用记忆体。
 
mysql_insert_id: 传回最后一次使用 INSERT 指令的 ID。
 
mysql_list_fields: 列出指定资料表的栏位 (field)。
 
mysql_list_dbs: 列出 MySQL 伺服器可用的资料库 (database)。
 
mysql_list_tables: 列出指定资料库的资料表 (table)。
 
mysql_num_fields: 取得传回栏位的数目。
 
mysql_num_rows: 取得传回列的数目。
 
mysql_pconnect: 开启 MySQL 伺服器长期连线。
 
mysql_query: 送出一个 query 字串。
 
mysql_result: 取得查询 (query) 的结果。
 
mysql_select_db: 选择一个资料库。
 
mysql_tablename: 取得资料表名称。
 

ODBC函数
使用ODBC函数需安装MYSQL ODBC
odbc_autocommit: 开关自动更动功能。

mysql让存储结果分页,用于复杂查询。

似乎讨论分页的人很少,难道大家都沉迷于limit m,n?
在有索引的情况下,limit m,n速度足够,可是在复杂条件搜索时,
where somthing order by somefield+somefield
mysql会搜遍数据库,找出“所有”符合条件的记录,然后取出m,n条记录。
如果你的数据量有几十万条,用户又搜索一些很通俗的词,
然后要依次读最后几页重温旧梦。。。mysql该很悲壮的不停操作硬盘。

所以,可以试着让mysql也存储分页,当然要程序配合。
(这里只是提出一个设想,欢迎大家一起讨论)

ASP的分页:在ASP系统中有Recordset对象来实现分页,但是大量数据放在内存中,而且不知道什么时候才失效(请ASP高手指点).
SQL数据库分页:用存储过程+游标方式分页,具体实现原理不是很清楚,设想如果用一次查询就得到需要的结果,或者是id集,需要后续页时只要按照结果中的IDs读出相关记录。这样只要很小的空间保留本次查询的所有IDs. (SQL中的查询结果不知道怎样清楚过期垃圾?)

这样,可以让mysql模拟存储分页机制:
1. select id from $table where $condition order by $field limit $max_pages*$count;
     查询符合条件的IDs.
     限定最大符合条件的记录数量,也可以不加。
2. 因为php在执行结束后所有变量都要lost,所以可以考虑:
     方案a. 在mysql建立临时表,查询结果用一个时间或随机数作为唯一标志插入。
      其中建立page1~pagen个字段,每个字段保存该页中需要的ids, 这样一个id对一条记录.
     方案b. 如果打开session,也可以放在session中保存,实际上是放在文件中保存。
         建立一个$IDs数组,$IDs[1]~$IDs[$max_pages]. 考虑到有时候用户会开几个
         窗口同时查询,要为$ids做一个唯一标志,避免查询结果相互覆盖。二维数组
         和$$var都是好办法。
3. 在每页页的请求中,直接找到对应的IDs,中间以","间隔:
      select * from $table where id in ($ids); 速度绝对快

[!--infotagslink--]

相关文章