Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
通过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


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
 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


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
 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


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

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

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


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

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


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

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))


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
 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中的字段


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
问题: 取出公司销售员工最近的订单编号及订单日期
 老办法,多次取值。实际是重复查询,查询一次返回一个值,不能做到查询一次得到所有结果
   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 


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

为使用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中不存在,故报错!
注:查看数据库兼容级别:数据库 – 属性 – 选项


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
1,分区作用:将数据分放到多个物理磁盘上,利用并行,多个磁盘同时吞吐以提升IO能力,同时每个分区数据量小,也减少了数据的扫描,提升了命中速度。实际上表逻辑上并未拆分,只是分散存储于不同的物理文件上,相当于把一张表大数据无限极细化到多张表上,多个驱动上,但是访问时却还是一样的访问,因为本身并未新建任何表。
注:即使放到一块磁盘上,因每个分区数据量小,扫描范围减少,也能提高速度。
表分区方法:1,按时间分区:好处,查询速度快。坏处:因当前数据一直写到一块分区上,故写不快。
                       2,HASH分区:数据均匀的分散到各分区,好处:因当前数据写到不同分区,故写快。但在查询方面,要联合多个分区,故查询不快。
注:分区分为硬件与软件分区,此页是软件分区。硬件分区指用磁盘阵列的方式分区,硬件负责将数据将到不同磁盘上,查询与写入速度都会提高。
操作:指定数据要分区的位置-创建文件组及对应文件, 数据以何种规则适移到分区上-创建分区函数, 进行数据迁移。

操作:指定数据要分区的位置-创建文件组及对应文件, 数据以何种规则适移到分区上-创建分区函数, 进行数据迁移。
步骤:
/*1,指定数据存放位置:增加文件组,并指定文件存放位置*/
ALTER DATABASE BRM_LVJIAN
ADD FILEGROUP [gf_bdorder_50]
ALTER DATABASE BRM_LVJIAN
ADD FILEGROUP [gf_bdorder_100]
ALTER DATABASE BRM_LVJIAN
ADD FILEGROUP [gf_bdorder_150]

ALTER DATABASE BRM_LVJIAN
ADD FILE ( NAME = N'gf_bdorder_50',
FILENAME = N'g:\Mssql_Filegroup\bdorder_50.ndf' , SIZE = 300MB , FILEGROWTH = 10% )
TO FILEGROUP [gf_bdorder_50]

ALTER DATABASE BRM_LVJIAN
ADD FILE ( NAME = N'gf_bdorder_100',
FILENAME = N'I:\Mssql_Filegroup\bdorder_100.ndf' , SIZE = 300MB , FILEGROWTH = 10% )
TO FILEGROUP [gf_bdorder_100]

ALTER DATABASE BRM_LVJIAN
ADD FILE ( NAME = N'gf_bdorder_150',
FILENAME = N'I:\Mssql_Filegroup\bdorder_150.ndf' , SIZE = 300MB , FILEGROWTH = 10% )
TO FILEGROUP [gf_bdorder_150]

/*2,指定数据如何存放:创建分区函数*/

--LEFT,RIGHT指定"="是在最左边还是右边
--LEFT: &lt;=1, 1&lt;10&lt;=20, &gt;20
--RIGHT: &lt;1,1&lt;=10&lt;20, &gt;=20
CREATE PARTITION FUNCTION [partitionFunc_bdOrder] (int)
AS RANGE LEFT FOR VALUES ('500000','1000000')

select max(id) from bdorder

/*3,数据的迁移,应用分区位置与函数,为了方便,将二者合二唯一,提出分区架构的概念*/
CREATE PARTITION SCHEME [partitionScheme_bdOrder]
AS PARTITION [partitionFunc_bdOrder]
TO ([PRIMARY],gf_bdorder_50,gf_bdorder_100,gf_bdorder_150)

--数据迁移到分区
ALTER TABLE dbo.bdOrder DROP CONSTRAINT PK_BDOrder
ALTER TABLE  dbo.bdOrder add CONSTRAINT PK_BDOrder PRIMARY KEY CLUSTERED (ID)
ON [partitionScheme_bdOrder](ID)

--恢复成原来的默认状态,因原来的分区架构是<span style="color: #ff0000;">PRIMARY</span>,故修改表即可,如下:
ALTER TABLE dbo.bdorder DROP CONSTRAINT PK_BDOrder
ALTER TABLE  dbo.bdorder add CONSTRAINT PK_BDOrder PRIMARY KEY CLUSTERED (ID)
ON [PRIMARY]

/*查询*/
--分区
SELECT * FROM SYS.PARTITIONS WHERE OBJECT_ID = OBJECT_ID('dbo.bdOrder')

--数据所在分区
SELECT  $PARTITION.[partitionFunc_bdOrder](1000000)

SELECT top 20 id,orderno,orderdate,$PARTITION.[partitionFunc_bdOrder](id)  FROM bdOrder
ORDER BY newid()

--数据分布

SELECT $PARTITION.partitionFunc_bdOrder(id) AS Partition_num,
MIN(Id) AS Min_value,MAX(Id) AS Max_value,COUNT(1) AS Record_num
FROM dbo.[bdorder]
GROUP BY $PARTITION.partitionFunc_bdOrder(id)
ORDER BY $PARTITION.partitionFunc_bdOrder(id)

select * from
sys.partition_range_values

/*若数据量增大,需要增加分区,扩大范围,操作如下*/
操作方法:增加分区,增加范围

ALTER DATABASE [D] ADD FILEGROUP [GF2]
ALTER DATABASE [WSBOOK] ADD FILE ( NAME = N'GF2', FILENAME = N'E:\E\E1\DGF2.ndf' , SIZE = 5MB , FILEGROWTH = 10% )
TO FILEGROUP [GF2]

为架构添加范围
ALTER PARTITION SCHEME [D_PARTITION_SHEME]
NEXT USED GF2
这句话就是让下一个分区使用和现在已经存在的分区GF2分区中,

2.添加一个范围
ALTER PARTITION FUNCTION [D_PARTITIONFUNC]()
SPLIT RANGE ('700000')

可以合并一个范围,其实就是<span style="color: #ff0000;">删除分区</span>,如MERGE RANGE(要删除的原分区界点)

ALTER PARTITION FUNCTION [D_PARTITIONFUNC]() MERGE RANGE ('400000')
3.查询分区分布

SELECT * FROM SYS.PARTITIONS WHERE OBJECT_ID = OBJECT_ID('dbo.B')

4.删除分区
DROP PARTITION SCHEME [D_PARTITION_SHEME]
DROP PARTITION FUNCTION [D_PARTITIONFUNC]


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

制约查询速度的有两方面,一是找到,二是取出,分别对应的是扫描数据与IO吞吐,扫描数据的提升通过建立合适的索引解决,而提升IO可以考虑将大表进行分区,分到多个物理磁盘上,通过并行方式提升IO能力。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
一个新的SQL Server 2005安装总是包括四个数据库:master、model、tempdb和msdb。还包含第五个“隐藏的”数据库Resource

1,model 数据库是 Microsoft SQL Server 创建其他数据库(包括 tempdb 数据库和用户数据库)时使用的模板。创建数据库时,model 数据库的全部内容(包括数据库选项)都会被复制到新数据库中。

2,tempdb 系统数据库是连接到 SQL Server 实例的所有用户都可用的全局资源,它保存所有临时表和临时存储过程。

3,master:账号、服务器信息,在 SQL Server 2005 中,系统对象不再存储在 master 数据库中,而是存储在 Resource 数据库中

4,Resource:Resource数据库的物理文件名为 Mssqlsystemresource.mdf,默认情况下,此文件位于 x:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\Mssqlsystemresource.mdf。
SQL Server 系统对象(例如 sys.objects)在物理上持续存在于 Resource 数据库中,但在逻辑上,它们出现在每个数据库的 sys 架构中。Resource 数据库不包含用户数据或用户元数据。

SQL Server 不能备份 Resource 数据库。Resource 数据库依赖于 master 数据库的位置。如果移动了 master 数据库,则必须也将 Resource 数据库移动到相同的位置。

5,msdb,包括计划信息、备份与还原历史记录信息、邮件信息
backupmediafamily --备份文件地址
backupset         --备份操作历史
restorefile		  --还原文件地址                  --
restorehistory    --还原操作历史
--备份详细
SELECT b.database_name,b.backup_start_date,b.backup_finish_date,b2.physical_device_name
FROM backupset b
JOIN backupmediafamily b2 ON b.media_set_id = b2.media_set_id
ORDER BY b.backup_start_date DESC

sysjobs --job
sysjobhistory --job执行历史

SELECT * FROM sysjobs
SELECT * FROM sysjobschedules
SELECT * FROM sysjobsteps
--job详细
SELECT a.job_id,a.name,s.next_run_date, s.next_run_time,
s2.step_name,s2.command
FROM sysjobs a
JOIN sysjobschedules s ON a.job_id = s.job_id
JOIN sysjobsteps s2 ON a.job_id = s2.job_id

--job状态
--取出在执行的job
 exec msdb.dbo.sp_help_job @Category_Name = N'REPL-Merge',@execution_status = 1
execution_status:
1 正在执行。
2 正在等待线程。
3 在两次重试之间。
4 空闲。
5 挂起。
7 正在执行完成操作
--不过,若想将存储过程执行的结果放到一临时表中,上述存储过程将报嵌套错误,此时,应用master.dbo.xp_sqlagent_enum_jobs
exec master.dbo.xp_sqlagent_enum_jobs 1,hello  
/*p_sqlagent_enum_jobs <is sysadmin (0 or 1)>,
                        <job owner name>
                       [, <job id>]

    The first parameter identifies whether you want to return information about all jobs on the server, 
    or just jobs owned by a particular job owner. If you specify "0" for this first parameter, 
    it means you want to return job information for a particular job owner. If you specify a "1," 
    it means you want information for all jobs. The second parameter identifies the job owner. 
    This parameter is required on all calls to this XP but is only used when you specify "0" for the 
    first parameter. The third and last parameter only needs to be provided if you want to return 
    information about a particular job_id. 
*/
参考:http://www.databasejournal.com/features/mssql/article.php/10894_3491201_2/Detecting-The-State-of-a-SQL-Server-Agent-Job.htm

--开关job
msdb.dbo.sp_stop_job @job_id = 'adfsdfs-sdfsdf'
msdb.dbo.sp_start_job @job_id ='adfsdfs-sdfsdf'

sysmail_mailitems --邮件明细






Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
DECLARE @TempTable table(UserID int , UserName nvarchar(50));
insert into @TempTable (UserID,UserName) values (1,'a')
insert into @TempTable (UserID,UserName) values (1,'b')
insert into @TempTable (UserID,UserName) values (1,'c')
insert into @TempTable (UserID,UserName) values (2,'d')
insert into @TempTable (UserID,UserName) values (2,'e')
insert into @TempTable (UserID,UserName) values (2,'f')

--以XML节点式一行存数据,节点名即是列名
select UserID,UserName from @TempTable FOR XML PATH

--PATH中的内容指定根结点名称,若无,则默认为root
select UserID,UserName from @TempTable FOR XML PATH('lzy')

--指定顶级根结点名称
select UserID,UserName from @TempTable FOR XML PATH('lzy'), root ('Root')

--若结果集中无列名,那么节点名也就没有,数据就显示到了一行
select convert(varchar(50),UserName) +','? from @TempTable s WHERE s.UserID = 1

--stuff用来去掉多余的逗号
SELECT DISTINCT t.UserID,
STUFF((select ',' + convert(varchar(50),UserName)? from @TempTable s WHERE s.UserID = t.UserID FOR XML PATH('')),1,1,'')
FROM @TempTable t


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
 为结果集构造行号,实际上是为结果集指定顺序,要排序的话就要知道排序规则:Order By
如:SELECT ROW_NUMBER() OVER(ORDER BY id DESC)AS rownum,
       departname  FROM mdDepartment md
应用:mysql的limit即可使用:
SELECT * FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY id DESC)AS rownum,departname
FROM mdDepartment md
) AS a
WHERE a.rownum>=3 AND a.rownum<=5      --返回3到5行


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
CTE: Common Table Express 指定临时命名的结果集

1, 当sql语句比较大时,可以用CTE将小结果集拆分,以便阅读
    WITH mycre(id,name) AS ( select id ,name from mddepartment )
    SELECT * FROM frmuser JOIN mycre ON frmuser.DepartmentID= mycre.id
 注:1)CTE 之后必须直接使用,间隔sql语句就会失效
        2)在用with时并不会执行查询,只是凑sql语句,只有当with后面的select *引用cte时才会执行

2,递归使用,依次引用自身。递归 CTE 定义至少必须包含两个 CTE 查询定义(一个定位点成员和一个递归成员)
 WITH departments(id,Departname,depth) as(
    SELECT id,Departname,1 depth FROM mdDepartment md
    WHERE md.ParentID = 2   --找到广告商务部的直接子部门 定位点成员,depth指定深度
    UNION ALL
    SELECT md.id,md.Departname,depth+1 FROM mdDepartment md --找到子部门的子部门 递归成员
    JOIN departments d ON md.ParentID = d.id
   
)
SELECT * FROM departments
    注:1)定位点成员之间必须使用UNION ALL、UNION、INTERSECT、EXCEPT集合运算符,最后一个定位点成员与递归成员之间必须使用UNION ALL,递归成员之间也必须使用UNION ALL连接,定位点成员和递归成员中的字段数量和类型必须完全一致,递归成员的FROM子句只能引用一次CTE对象。
           2)递归成员中不允许出现下列项
              SELECT DISTINCT
              GROUP BY
              HAVING
              标量聚合
              TOP
              LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)
              子查询


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

1,选择语句:

* 每句后加分号;
* else if 应为elseif,中间不留空格。mssql为:if begin … end else if begin … end 形式

IF ( _TranType=’Insert’ ) THEN
INSERT INTO bmdcustomer(CustomerName,CustomerAddress,tel,Remark,Type,LastEditBy,LastEditDate)
VALUES(_CustomerName,_CustomerAddress,_tel,_Remark,_Type,_LastEditBy,now());
SET _Id = @@IDENTITY;

ELSEIF ( _TranType=’Update’ ) THEN
INSERT INTO bmdcustomer(CustomerName,CustomerAddress,tel,Remark,Type,LastEditBy,LastEditDate)
VALUES(_CustomerName,_CustomerAddress,_tel,_Remark,_Type,_LastEditBy,now());
SET _Id = @@IDENTITY;
ELSE
SELECT 1;
END IF;

2,日期:当前时间,Mysql: now(), MsSql:getdate()


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
1,将循环因子1,2,3,4,5....存入一表中,用此表与目标表进行关联即可。
2,例子:提取 字符串  ‘13604784785薛小姐’非中文部分
create table #tt(n int)          --循环数
declare @tt int
set @tt=1
while @tt<=200
begin
        insert #tt values(@tt)
        set @tt=@tt+1
END
CREATE TABLE #ts(tel VARCHAR(100))
INSERT INTO #ts VALUES ('13604784785薛小姐')

declare @string varchar(200)
SELECT TOP 1 *,SUBSTRING(tel,1,n-1) FROM (
SELECT tel,n,case when SUBSTRING(tel,n,1) LIKE '[0-9]' THEN NULL ELSE STUFF(tel,n,0,'#') END AS 'string'
FROM #ts JOIN #tt ON n < LEN(#ts.tel))m1
WHERE m1.string IS NOT null


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

一般用法为:
select case 1 when 1 then ‘yes’ when 2 then ‘no’ end
即为:when 1=1 取 ‘yes’
when 1=2 取 ‘no’
多条件为:
SELECT CASE WHEN 1=2 THEN 2 when 3=3 then 3 ELSE 4 end
case后不带参数,when可作多个条件

带语句使用:
–若是一次部门,输出第一次下订单日期,若是二次部门等,输出第一次分配客户日期
SELECT md.DepartName,a.UserName,CASE(md.DepartType)
WHEN ‘first’
THEN (SELECT MIN(orderdate) FROM bdOrder bo WHERE bo.SalesStaff=a.Account )
ELSE (SELECT MIN(opendate) FROM bdCustomerAllocate bca WHERE bca.SalesStaff =a.Account ) END
FROM frmuser a(NOLOCK)
JOIN mdDepartment md ON a.DepartmentId = md.ID
注: THEN 后面是一个值,故SELECT要用括号括起来。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

@@ROWCOUNT 返回受上一语句影响的行数,如select取出的行数,(可用此判断查询是否有结果),update更新的行数。
注:@@RowCount 是全局变量,它是基于session的,每个会话有自己的全局变量,在任一时间点下@@RowCount是安全的。 也就是说它永远是返回该session前一条sql所影响的行数.


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
行变列

    注:要变列的行单元对应的数据须唯一,故在下面的子查询中先对目标行单元进行了分组,以保证唯一性。
    1,用case指定条件
    SELECT f.UserName,
    SUM(CASE CONVERT(VARCHAR(10),b.OrderDate,120) WHEN '2011-03-10' THEN b.Amount ELSE 0  END) AS '2011-03-10',
    SUM(CASE CONVERT(VARCHAR(10),b.OrderDate,120) WHEN '2011-03-11' THEN b.Amount  ELSE 0 END) AS '2011-03-11',
    SUM(CASE CONVERT(VARCHAR(10),b.OrderDate,120) WHEN '2011-03-12' THEN b.Amount  ELSE 0 END) AS '2011-03-12' 
    FROM bdAchievement a(NOLOCK)
    JOIN bdOrder b(NOLOCK) ON a.OrderNo = b.OrderNo
    JOIN frmuser f ON a.SalesStaff = f.Account
    WHERE a.RootDepartmentID  = 184 AND b.OrderDate >='2011-03-10'
    GROUP BY F.UserName

    2,用SQL SERVER2005提供的关键词PIVOT来执行
    行变列:将多行的值合并放到列上去,这就需要一个聚合函数,此外要指定拆分成行(列一行)的列并且此列按如何规则分配到行上去
    SELECT * FROM (
    SELECT f.UserName,CONVERT(VARCHAR(10),OrderDate,120) orderdate,b.Amount 
    FROM bdAchievement a(NOLOCK)
    JOIN bdOrder b(NOLOCK) ON a.OrderNo = b.OrderNo
    JOIN frmuser f ON a.SalesStaff = f.Account
    WHERE a.RootDepartmentID  = 3 AND b.OrderDate >='2010-02-10') O
    PIVOT (SUM(amount) FOR orderdate IN([2011-03-10],[2011-03-11],[2011-03-12],[2011-03-13])) AS c
    将列订单日期转换到行上去,分成多个列,规则是[2011-03-10],[2011-03-11],[2011-03-12],[2011-03-13]),并对要求的amount求和

    同样列变行为:UNPIVOT
注:应用限制,列拆分规则是有限的几个,即行名是可指定的,若行名是未知数,那查出的数据将不知放到哪一列,故这样的行转列是则不可执行

注: PIVOT 与CASE 方法的区别:PIVOT简洁,但只能将一个列的列值转为列,没有CASE灵活


3,将列直接转成行
现有一客户电话表,客户电话最多4个,要求以行形式显示出来

CREATE TABLE tmpTable(CustomerID INT,Tel VARCHAR(20))

INSERT INTO tmpTable(CustomerID,Tel) VALUES(222,'13587654321')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(222,'13587654322')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(222,'13587654323')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(222,'13587654324')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(333,'13587654331')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(333,'13587654332')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(444,'13587654341')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(444,'13587654332')
INSERT INTO tmpTable(CustomerID,Tel) VALUES(444,'13587654332')

SELECT * FROM (
SELECT customerid,tel, ROW_NUMBER () OVER ( PARTITION BY CustomerID ORDER BY  tel DESC )r
FROM tmpTable tt)m
PIVOT (max(tel) FOR r IN ([1],[2],[3],[4]) ) AS t