2011年3月 的存档
2011三月31

字符串字段每一位上类型的判断

sql server 评论关闭

如查找用户名称仅由数字、字母组成的集合。
定义集合A
每一位都是字母、数字
对应:若元素有一位不是字母、数字则它就不属于A,对每一位上的限定用 NOT LIKE ‘%[限定范围]%’
SELECT * FROM frmUser b(NOLOCK)
WHERE b.WorkNo NOT IN(
SELECT a.WorkNo
FROM frmuser a(NOLOCK)
WHERE a.WorkNo NOT LIKE ‘%[0-9,a-z]%’)

2011三月30

Distinct的使用

sql server 评论关闭
Distinct不仅可用在SELECT中,也可用在COUNT内
如:查询出所有在一线、二线部门都出过单的客户
方法:按客户ID分组,对成单的部门进行DISTINCT,次数大于2的即是
SELECT a.CustomerID
FROM bdOrder a(NOLOCK)
JOIN frmuser f ON a.SalesStaff = f.Account
JOIN mdDepartment md ON f.DepartmentId = md.ID
WHERE md.DepartType IN('first','second')
AND a.OrderDate >='2011-01-01'
GROUP BY a.CustomerID
HAVING COUNT(DISTINCT md.DepartType) >=2
2011三月28

存钱罐与数据库

sql server 评论关闭

存钱罐,平时存放5毛,1毛,1块的零钱,现在找出所有面值为5毛的。
方案1:存钱罐只有一个,所有零钱都在其中,在里面翻找全部零钱,找出所有5毛的。对应全表扫描。
方案2:将面值分类,存放到不同的存钱罐中,找时直接拿出即可。只是要增加额外的存钱罐,并且在放零钱时要注意放到对应的存钱罐中。对应数据库索引的存储空间,及在插入更新时要对索引进行操作,不过换来的是查询速度的提升。

当存钱量上升到多倍时,找5毛的硬币所费时间并没有增长多少,所花费的时间在于取出数量。即:数据量增加,查找时间并不会增长多少,只是增加了I/O时间。

2011三月28

SQL Server服务重启注意

sql server 评论关闭

重启SQL Server服务时,最好使用配置管理器,它会自动进行一些额外的配置,如在Windows注册表中设置权限使新的账号能够读取SQL Server的设定。使用配置管理器来修改密码会立即生效,无需重启服务。

2011三月26

SQL SERVER体系结构

SQL Server体系结构由四大组件构成:协议、关系引擎(查询处理器)、存储引擎、SQLOS.
协议(秘书):进行翻译与传达工作,它将接收到的请求转换成关系引擎能够识别的形式。并将关系引擎处理的最终结果转换成客户端能够理解的形式返回到客户端。
关系引擎(管理者):接受SQL批处理,以及决定如何处理,对SQL进行解析、编译及优化、执行,若需要数据,它会发送一个请求到存储引擎。
存储引擎(文件柜):负责管理所有的数据访问,包括基于事务的命令和大批量操作。
SQLOS:负责各层之间的沟通、例如线程调度、死锁检测等。

协议:在SQL Server的配置管理器中可以看到。
1,共享内存(本机访问):客户端通过该协议连接到本地计算机上的SQL Server运行实例
2,命名管着(局域网访问):为局域网而开发的协议。应用于局域网内因为它要求客户端必须具有访问服务器资源的权限。
3,TCP/IP(网络访问):在网络之间连接,可以用来在不同的硬件体系结构和操作系统的计算机网络之间进行通讯。
4,虚拟接口适配器(VIA):它是一种与VIA硬件一起使用的专门化的协议。
通常,TCP/IP 在慢速 LAN、WAN 或拨号网络中效果较好。而当网络速度不成问题时 Named Pipes 则是更好的选择,因为其功能更强、更易于使用并具有更多的配置选项。
经测试:只开TCP/IP,本机、局域网都可访问
只开Named Pipes:本机可访问,局域网不行,局域网要有访问本机的权限,设置后才可访问
只开共享内存:都不能访问
重要性:TCP/IP > Named Pipes > 共享内存

2011三月25

表和索引的结构

sql server 评论关闭

1,SQL SERVER 存储数据的最小单位是页,大小为8KB,它可以包含表或索引数据、分配视图、可用空间信息等。
1)它是SQL SERVER可以读写的最小I/O单位,所以即使访问一行,SQL SERVER也要把整个页加载到缓存,再从缓存中读取数据。
2)页的大小是8KB,即8192字节,故行的大小不会超过8192字节,最大值是8060字节,因为8192-96(标头信息)- 2(页尾维护的行指针)- 34(保留字节) = 8060
3)在2005之前的版本中行不能跨多页,而2005之后是可以的,当行大小超过8060字节后,这些类型的值将被移动到一个称为行溢出分配单元的页中,而在原始页上保留一个24字节的指针,指向行外的数据。

2,8个物理上连续的页组成的单元称为区。

3,表没有索引时组织为堆,有时组织为B树,堆是无序的,给定一个值,在对于节点处不知是在此节点的左子节点还是右子节点,而B树是有序的,给定一个值是可以知道是向左走还是右走。
概念:堆是一种特殊的二叉树,每个接点的关键值都大(或小于)它的左右孩子接点,一般指最大堆或最小堆
具备以下两种性质
1)每个节点的值都大于(或者都小于,称为最小堆)其子节点的值
2)除最后一层外每一层都是填满的,并且最后一层的树叶都在最左边

B树 :二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点;
二者区别:在于子结点上,B树是子结点比父结点小,右结点比父结点大,而堆没有这种性质。

2011三月24

为列值指定生成方式如用checksum

sql server 评论关闭

表设计中增加列,在列的计算所得列的规范中录入公式即可
持久代表值是否实际存储起来还是每次查询时重新生成
如:ALTER TABLE dbo.tmp ADD cs_Pname AS CHECKSUM(c1);
为列计算校验值,然后在此列上加上索引,则比一般的查询速度要快
应用:1,字符串比较没有数字比较来得快,故可增加一列存字符串的校验值,在此值上加索引进行比较,速度将提升很多

2,SELECT CHECKSUM(NEWID()) 返回随机数1到n: abs(CHECKSUM(NEWID()))%n + 1

3,CHECKSUM(NEWID()) 返回8-10位数字,故要求11位以上的随机不重复数,可采用:
SELECT right(right(abs(CHECKSUM(NEWID())),3) + CONVERT(varchar(50),abs(CHECKSUM(NEWID()))),11)

4,随机时间:
SELECT DATEADD(mi,ABS(CHECKSUM(NEWID())%(1+DATEDIFF(mi,’2011-05-14 13:00′,’2011-05-14 14:00′))),’2011-05-14 13:00′)

5,比较两行多个列是否相同
SELECT CHECKSUM(1,2,4)
SELECT DISTINCT OBJECT_ID,NAME,TYPE
FROM sys.tables tb
WHERE CHECKSUM(OBJECT_ID,NAME,type)
IN(
SELECT CHECKSUM(OBJECT_ID,NAME,type)
FROM (
SELECT OBJECT_ID,NAME,TYPE FROM sys.objects o
)obj
)
注: checksum不区分大小写,若要区分,要用BINARY_CHECKSUM

2011三月23

32位机最大使用内存

sql server 评论关闭

32位机能够寻址为:2^32次方 = 4G,而Windows系统本身会将2GB的地址空间留做已用。故所有应用程序最大内存空间为2G,SQL SERVER若想超过2G,需要开启AWE!
/3g开关,只是将用户可用物理内存调整为3g核心系统内存调整为1个g,提高用户程序的执行性能
/pae开关,只是用于在大于4g的物理内存时 识别出更多内存使用
awe 是帮助应用程序能寻址大于4g的空间
pae是开awe的前提。 pae是整体上开到4G以上,awe是让sql server可以大于4g以上,只开awe,因整体不允许超过4G,故开AWE也要开PAE

2011三月23

数据库监视-profiler使用

sql server 评论关闭
通过SQL Server?>Tools?>SQL Server Profiler启动
注:激活SQL Profiler跟踪约损耗1/7的性能,所以要谨慎使用。
1,通用页:跟踪的记录有两种保存方式:保存到文件和保存到表。通常选择保存到文件,不要把跟踪直接写入到表,这样会严重影响性能,把文件写到与数据库位置不同的磁盘是最快的方案。
2,模块选择:
Standard:创建跟踪的通用起点。捕获所运行的全部存储过程和 Transact-SQL 批处理。用于监视常规数据库服务器活动。
TSQL:捕获客户端提交给 SQL Server 的所有 Transact-SQL 语句及其发出时间。用于调试客户端应用程序。
TSQL_Duration:捕获客户端提交给 SQL Server 的所有 Transact-SQL 语句及其执行时间(以毫秒位单位),并按持续时间对其进行分组。用于识别执行速度慢的查询。
TSQL_Grouped:捕获提交给 SQL Server 的所有 Transact-SQL 语句及其发出时间。信息按提交语句的用户或客户端分组。用于调查某客户端或用户发出的查询。
TSQL_Locks:捕获客户端与异常锁事件一起提交到 SQL Server 的 Transact-SQL 语句。用于排除死锁、锁超时和锁升级事件的故障。
TSQL_Replay:捕获重播跟踪所需的 Transact-SQL 语句的详细信息。用于执行迭代优化,例如基准测试。

3,事件选择:若多是存储过程,则跟踪SP:Completed事件,若存储过程有很多操作,查看明细要跟踪SP:StmtCompleted.
若程序多是sql语句,则跟踪SQL:BatchCompleted与 SQL:StmtCompleted事件
在事件选择版块上点击列名,可以进行筛选,如指定数据库筛选:DataBaseName 类似于brm_lvjian_new.

4,1) 文件导出脚本,包装成一个存储过程 ,在此存储过程中 print @traceid
   2)执行此存储过程,根据打印出的@traceid来控制跟踪的执行与停止,之所以不用profiler的GUI界面,第一是profiler不便于分析,并且需要将数据写入到GUI,性能也不高。运行:EXEC [WorkTraceStart] 'brm_lvjian_new',@tracefile='d:\mytrace'
   3)控制跟踪:执行: EXEC sp_trace_setstatus @traceid, [0|1|2]    0: 停止 1:启动 2:删除
       注:在执行2)的存储过程后,里面有一个 EXEC sp_trace_setstatus @traceid, 1; 将启动跟踪。
       查看跟踪:sys.traces

4,分析保存的跟踪文件
1)导入
select CAST(textdata as nvarchar(max)) as tsql_code,duration
into Workload
from sys.fn_trace_gettable('C:\test\performancetrace_20100802.trc',NULL) as TT

2)分析
select convert(varchar(60),tsql_code),sum(duration) s,avg(duration) t from workload
where duration >=3000  --一般是执行时间在3秒以上的
group by convert(varchar(60),tsql_code)
order by s desc

5, 查询事件由哪些情形引发:
如查询执行计划重新编译由哪些引发:
SELECT e.name,v.subclass_name,v.subclass_value,tc.name,tc.[type_name]
FROM sys.trace_events e
JOIN sys.trace_subclass_values v ON e.trace_event_id = v.trace_event_id
JOIN sys.trace_columns tc ON v.trace_column_id = tc.trace_column_id
WHERE e.name = 'sp:recompile' --AND v.subclass_value < 100

6,使用:在图形界面上修改表的属性与通过tsql修改表的属性,如增加表字段长度,通过Profiler观察发现:
通过图形方式:是先转移全部数据到临时表,再删除表,然后重命名临时表为原来表名称,速度比较慢,而通过tsql发现只执行一条sql语句即可,故优先使用tsql
2011三月23

取出每日订单最大金额的前三名ROW_NUMBER

sql server 评论关闭
 1,取出所有日期中订单最大金额的前三名
  SELECT * FROM (
    SELECT CONVERT(VARCHAR(10),bo.OrderDate,120) date1, orderno,amount,
    ROW_NUMBER() OVER(ORDER BY bo.amount desc) AS numbers
    FROM bdOrder bo(NOLOCK)
    WHERE bo.OrderDate >='2011-03-19'
)m
WHERE m.numbers <=3
2,若想取出每日的前三名,就需要对数据进行按日期分组,不能用GROUP BY ,因为OVER中有amount,必须要在GROUP BY 中加上amount,也有失去了分组的意向。
    方法:在行级分组,利用强大的OVER,在行级对日期进行分组
    SELECT * FROM (
           SELECT CONVERT(VARCHAR(10),bo.OrderDate,120) date1, orderno,amount,
           ROW_NUMBER() OVER(PARTITION BY CONVERT(VARCHAR(10),bo.OrderDate,120) ORDER BY bo.amount desc) AS numbers
           FROM bdOrder bo(NOLOCK)
           WHERE bo.OrderDate >='2011-03-19'
    )m
     WHERE m.numbers <=3
2011三月22

SQL的同时操作性,select列表中的执行顺序

sql server 评论关闭
 SQL中的多个运算是同时进行计算的,即同时操作,all-at-once operation,与在select列表中的前后位置无关
如: update a
        set a.value1 = a.value2, a.value2 = a.value1  --同时发生,即时交换
        from tmpTable
由上知:1)select中的别名不能在同一select列表中使用。 如select max(id) mid, mid+1 from tmpTable 是错误的
             2)UPDATE t
                  SET t.c4 = convert(varchar(20),GETDATE(),120)
                  FROM tmp2 t
                  因执行是同时进行的,故t.c4得到的日期是相同的
             3)update a set a.value1 = 100 + (select max(c1) from tmpTable)    因执行是同时的,故最大值c1不会改变

4)应用:得到某一值,并将此值加1
                  update a set @value = value, value = value+1 from tmpTable
2011三月19

OLE DB访问接口”SQLNCLI”无法启动分布式事物

开发遇到的问题 评论关闭
建立复制分发的时候出现:OLE DB访问接口”SQLNCLI”无法启动分布式事物
原因:双方均要启动msdtc服务。
解决方法:双方电脑:
1.控制面板->管理工具->组件服务->计算机->我的电脑->右键->属性
2. 选择MSDTC页, 确认”使用本地协调器”
3.点击下方”安全配置”按钮
4. 勾选: “允许网络访问”,”允许远程客户端”,”允许入站”,”允许出站”,”不要求进行身份验证”.
5. 对于数据库服务器端, 可选择”要求对呼叫方验证”
停止分布式事务协调器服务,然后重新予以启动。
停止参与分布式事务的任何资源管理器服务(如 Microsoft SQL Server 或 Microsoft Message Queue Server),然后重新予以启动。
6.在双方防火墙中增加MSDTC.exe例外
可用命令行: netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable
7.dtC用到remoting的135端口,确保防火墙没有阻止
若还不行,修改host文件,将对方机器名和IP加入,因为远程服务器需通过发起服务器的机器名查找服务器。

注意:若是集群,则开群集DTC设置(在本地DTC下面)
或者在没有事务的情况下,不使用DTC
EXEC sp_serveroption @server = 'dpreport',@optname = 'remote proc transaction promotion', @optvalue = 'false'

2011三月16

执行计划

1,自右向左,自上而上
2,箭头的粗细表示每个图标之间移动的数据行数量以及数据行大小移动所需的相对本。
Table Scan:表扫描,扫描每一行。,就说明数据表上没有聚集索引
Index Seek(索引查找):索引查找意味着查询优化器使用了数据表上的非聚集索引来查找数据
Clustered Index Seek(聚集索引查找):这指查询优化器使用了数据表上的聚集索引来查找数据,性能很快。实际上,这是SQL Server能做的最快的索引查找类型
Clustered Index Scan(聚集索引扫描):在有聚集索引的表上执行扫描,不是聚集查找的原因是WHERE条件限制太少,没用到聚集索引字段。聚集索引扫描与表扫描相似,不同的是聚集索引扫描是在一个建有聚集索引的数据表上执行的。与标准的表扫描不同,聚集索引扫描并不会总是去查找数据表中的所有数据,所以聚集索引扫描一般都会比标准的表扫描要快。通常来说,要将聚集索引扫描改成聚集索引查找,你唯一能做的是重写查询语句,让语句限制性更多,从而返回更少的数据行

避免出现:表扫描,估计I/O开销与估计运算符开销越小越好
估计I/O开销:
用于执行操作的所有 I/O 活动的估计开销。此值应尽可能低。
估计运算符开销:
用于执行此操作的查询优化器的开销。此操作的开销以占查询总开销的百分比的形式显示在括号中。由于查询引擎选择最高效的操作来执行查询或执行语句,因此此值应尽可能低。

2011三月15

结果集比较EXCEPT与INTERSEC

sql server 评论关闭

EXCEP:返回左结果集不在右结果集中的记录
INTERSEC:返回两个结果集相同的记录

SELECT * FROM (
SELECT 1 id,1 name1 UNION ALL SELECT 2,2 UNION ALL SELECT 3,3)m
EXCEPT
SELECT * FROM (
SELECT 1 id,1 name1 UNION ALL SELECT 2,2 UNION ALL SELECT 4,4 )n

2011三月15

Sql加密与解密

sql server 评论关闭

SELECT EncryptByPassPhrase(
‘My Password Used To Encrypt This String in 2008.’,
‘hello,word!’)
解密:
SELECT CAST(DecryptByPassPhrase(
‘My Password Used To Encrypt This String in 2008.’,
MySecret) as varchar(max))

2011三月14

产生不重复的订单编号

设计好的思路 评论关闭

方法1: 抓取订单表中当前最大的编号,进行加1产生新的编号
优点:简单
缺点:当订单表很大时,速度将慢下来

方法2:建立一mdCurrentNo表,取出此表的值并增加1
优点:此表只有一条数据,故速度很快。
缺点:编号只能是递增的。

方法3:建立一mdCurrentNo表,同时建立一mdOrderNo表,里面存储了提前生成的随机不重复编号,结构为ID,No, 而mdCurrentNo的值存放的就是ID值,每次取出此ID JOIN mdOrderNo的ID,得到编号,然后将ID+1
优点:灵活
缺点:需要定时生成mdOrderNo的记录

2011三月12

SQL语句执行顺序

sql server 评论关闭
 1,FROM阶段
   1)从FROM执行,对于JOIN,两表进行交叉连接,求笛卡尔积得到一个结果集。
   2)根据ON条件,对结果集不满足条件的记录去除
   3)若有外连接,如LEFT,RIGHT等,再将满足条件的加入到结果集中
   4)执行APPLY,PIVOT,UNPIVOT等表达式
2,WHERE阶段:对于1步骤得到的虚表,将where条件为true的保留下来
3,GROUP BY 阶段 对虚拟表进行分组
4,HAVING阶段,对分组后的虚拟表进行筛选
5,SELECT/UPDATE/DELETE阶段,投影取得列数据,若有TOP,则会根据ORDER BY 子句来选择指定数量的行
6,ORDER BY 阶段 对上述结果进行排序,返回游标

由上知:1,GROUP BY 是HAVING的基础,需要先执行GROUP BY 再执行HAVING
        2, WHERE比SELECT先执行,故在SELECT中指定的虚列在WHERE条件中不可用,而SELECT比ORDER BY 先执行,故在SELECT中指定的虚列在ORDER BY条件中可以使用
     SELECT f.UserName,SUM(amount) amo --amo:虚列,指在原有表中不存在的列
     FROM bdOrder
     ORDER BY amo
       3,若使用ORDER BY,则返回的是一个游标,不能用在FROM后面,因为FROM后面跟的是结果集
        SELECT * FROM ( SELECT * FROM frmuser ORDER BY Account )f 这样是错误的
       例外:可通过加TOP解决
    SELECT * FROM ( SELECT TOP * FROM frmuser ORDER BY Account )f
4:当Select未使用Distinct时,Order By可使用Select之前的字段,即:即使在Select中不存在,但在表中存在的字段,Order By也可引用当Select使用Distinct时,Order By只能使用Select中的字段
2011三月12

一次查询计算返回多个值-APPLY

sql server 评论关闭
问题: 取出公司销售员工最近的订单编号及订单日期
 老办法,多次取值。实际是重复查询,查询一次返回一个值,不能做到查询一次得到所有结果
   SELECT a.UserName,
             (SELECT TOP 1 OrderNo
                FROM bdorder b
                WHERE b.SalesStaff = a.account
                  AND b.OrderDate >='2011-02-01'
                ORDER BY b.OrderNo DESC
              ) OrderNo,

                (SELECT TOP 1 OrderDate
                 FROM bdorder b
                 WHERE b.SalesStaff = a.account
                   AND b.OrderDate >='2011-02-01'
                 ORDER BY b.OrderNo DESC
                 )OrderDate 

 FROM frmuser a

新方法:查询一次返回一个结果集
SELECT a.UserName,b.OrderNo,b.orderdate
FROM frmuser a(NOLOCK)
  OUTER  APPLY(
      SELECT TOP 1 OrderNo,OrderDate
      FROM bdorder b
      WHERE b.SalesStaff = a.account
      AND b.OrderDate >='2011-02-01'
      ORDER BY b.OrderDate DESC
    )b
OUTER APPLY:相当于表中的LEFT JOIN
CROSS APPLY:相当于表中的JOIN 
2011三月12

将数据库兼容性由80提升到90引发的错误

sql server 评论关闭

为使用2005提供的新功能如行列转换pivot将将数据库兼容性由80提升到90,
sp_dbcmptlevel @dbname=’brm_lvjian’, @new_cmptlevel=90
报错:如果指定了 SELECT DISTINCT,那么 ORDER BY 子句中的项就必须出现在选择列表中。
语句为:
SELECT distinct a.orderno,
CONVERT(varchar(10), OrderDate, 20) AS OrderDate
FROM bdorder a
WHERE a.OrderDate >=’2011-02-01′
ORDER BY a.OrderDate
原因在80(sqlserver2000) 中对于ORDER BY 将忽略列前缀。故上面的ORDER BY a.OrderDate执行的是ORDER BY OrderDate
而在90(2005)中是不忽略列前缀的,上面的ORDER BY a.OrderDate因在select中不存在,故报错!
注:查看数据库兼容级别:数据库 – 属性 – 选项

2011三月11

电脑访问不了局域网资料

开发遇到的问题 评论关闭

网络连接配置正确,只是访问\\192.168.16.223这样的资源提示无法访问。
原因:将服务中的Workstation启动即可。
注:WordStation:维护远程资料访问功能