sql知识随笔(二)

第一部分 基础知识

Join

Join 是inner join的缩写

示例:

SELECT *

FROMPersons

INNER JOINOrders

ONPersons.Id_P = Orders.Id_P

ORDER BYPersons.LastName

 

所得结果是persons表和orders表的交集,即符合on条件的两个表数据才被获取。

 

在sqlserver中调试存储过程传入临时表

 

在sqlserver中调试:

USE [mybase]

GO

 

--drop table #MyTemp

create table #MyTemp --创建临时表

(   

   快递单号                varchar(100),

   订单编号                varchar(100)           

);

 

insert into #MyTemp values('1234','SC141001000002')

DECLARE    @return_valueint

 

EXEC   @return_value= [dbo].[sp_T存储过程1]

       @user= N'aaa',

       @lup_express= N'中',

       @localNum= '',

       @OrderNum= 'tempdb..#MyTemp',

       @ip= N'2.2.2.2',

       @dbname= N'mybase.'

 

SELECT 'ReturnValue' = @return_value

 

GO

 

存储过程的编写:

CREATE PROCEDURE [dbo].[sp_T存储过程1]

 @user varchar(20)

,@lup_express varchar(20)

,@localNum varchar(100)  

,@OrderNum varchar(100)    --临时表

,@ip varchar(255)

,@dbname varchar(20)

as/*

 

insert into @T select * from  '+@OrderNum+'—这么用

 

 

注意:临时表仅对当前连接有效,换一个查询窗体都不起作用。

 

 

Sql中的三目运算符(Case When Then

CASE WHENisnull(d.ad0554,'''')!=''淘宝'' THEN b.订单编码 ELSE c.ac0530 end 外部平台编号

 

 

清空表

有三种方式:

Truncate table/droptable/delete

Delete操作会产生大量的日志,支持还原。若对几千万两级的表实施delete,则数据库将会卡死。

Truncate table 和drop table 只产生少量日志,适合大数据量的表进行清空。

如果大数据量的表,想要保留一小部分行,其余行全部删除,如下方式:先把要保留的数据放入临时表,在drop,再重新建立该表,再把临时表中的数据导入。

 

 

临时表

 

 

l  临时放数据的表:logs..表1

l  每次数据库重启的时候会清除:tempdb下的普通表

l  在会话或batch中用到的临时表,使用完自动删除:#t

l  全局临时表,使用完自动删除,基本不用:##表1

l  表变量:declare @a table(a int,b int)

l  公用表达式,考虑到性能慎用:;with vt sa (select * from…)

 

其中,declare @T table不能跨越层级用,即(exec(‘your sql’),外部声明的@T在your sql中是不能引用的)

 

注意:1#表不同于其他类型临时表,是自动创建在tempdb..库下
2#表只对当前线程当前会话有效,会话结束后自动删除,因此创建时不必判断是否存在。

3在判断#表是否存在时,如if Object_id(''logs..临时表2'') is not null,必须指定#表的所在库。

4其他临时表新建时,如果没有指定数据库,建立在默认当前库下。

5可以这种写法指定数据库:

6表变量在批处理结束后自动被清除

表变量详解http://www.cnblogs.com/kissdodog/archive/2013/07/03/3169470.html

 

‘#临时表’的创建

方法1: select * into #t from table1

方法2:

 create table #t(intid,int idd)

  insert into #t(id,idd)

  select id,idd from table1


Sysobjects

存在于每个数据库下面的一张表。

对象表。保存当前数据库的对象,如约束、默认值、日志、规则、存储过程

http://baike.baidu.com/view/5995807.htm?fr=aladdin给出了此表的含义。

sysobjects 重要字段解释:

sysObjects (

Name sysname,--object 名称

id int, --objectid

xtype char(2),-- object 类型

type char(2), --Object 类型(与xtype 似乎一模一样? 有点郁闷…)

uid smallint, --object 所有者的ID

... --其他的字段不常用到。

)

例如:

Use [master]—注意如这里不写引用的表明,就需要from后面加上数据库名称。

select top 10 * from sysobjects where type='U'and name='userinfw'

 

exec [master].dbo.sp_executesqlN'if exists(select 1 from sysobjects where name =''sp_T存储过程2' and type =''P '') drop Procedure [sp_T存储过程2] '

 

Object_id

可以代替sysObjects,如:

ifObject_id(''logs..user_临时表1'')is not null  drop table logs..user_临时表1

 

ROW_NUMBER()OVER函数

详细介绍http://www.cnblogs.com/fxgachiever/archive/2010/09/15/1826792.html

作用是取得表中每行的行号。

示例,获取排名:

create table ScanRecord(name VARCHAR(50),goods  VARCHAR(50))

 

go

insert into ScanRecord (name ,goods ) values('张三','s001')

insert into ScanRecord (name ,goods ) values('李四','s002')

insert into ScanRecord (name ,goods ) values('王五','s003')

insert into ScanRecord (name ,goods ) values('张三','s004')

insert into ScanRecord (name ,goods ) values('李四','s005')

insert into ScanRecord (name ,goods ) values('张三','s006')

 

 

if object_id('tempdb..#T') is not null   drop table #T

select count(name) 数量,name into #T from ScanRecordgroup by name order by 数量 desc

select ROW_NUMBER() over(ORDER BY 数量 desc) 名次,* from #T

 

 

 

CHARINDEX函数

CHARINDEX函数返回字符或者字符串在另一个字符串中的起始位置。CHARINDEX函数调用方法如下:

       CHARINDEX( expression1 , expression2 [ , start_location ] )

       Expression1是要到expression2中寻找的字符中,start_location是CHARINDEX函数开始在expression2中找expression1的位置。

       CHARINDEX函数返回一个整数,返回的整数是要找的字符串在被找的字符串中的位置。假如CHARINDEX没有找到要找的字符串,那么函数整数“0”。让我们看看下面的函数命令执行的结果:

      CHARINDEX('SQL','Microsoft SQL Server')

     这个函数命令将返回在“Microsoft SQL Server”中“SQL”的起始位置,在这个例子中,CHARINDEX函数将返回“S”在“MicrosoftSQL Server”中的位置11。
接下来,我们看这个CHARINDEX命令:

     CHARINDEX('7.0', 'Microsoft SQL Server 2000')

     在这个例子中,CHARINDEX返回零,因为字符串“7.0” 不能在“Microsoft SQL Server”中被找到。

 

 

 

Cast

CAST函数用于将某种数据类型的表达式显式转换为另一种数据类型。CAST()函数的参数是一个表达式,它包括用AS关键字分隔的源值和目标数据类型。

语法:
CAST (expression AS data_type)

例如:

select top (cast('''+@numberSum+'''as int))

      a.TC0324 快递单号

      from '+@dbname+'.T0481 a wherea.TB0147 = ''0''  and a.td0006 = '''+@express+'''and a.TC0324 <> ''''

 

 

sp_executesql

位于master库下的一个扩展存储过程。用于执行一段sql代码。

declare @count int,@tableNamenvarchar(50),@SQLString nvarchar(max),@proid int,@id int,@ParmDefinitionnvarchar(max);

set @tableName='table27';

set @proid=433;

set @id=159;

--set @sql=N'select@count=count(empid) from table27'

set @SQLString=N'select@countOUT=count(empid) from '+@tableName+' where proid=@proid1 and id<@id1and state!=4';

set @ParmDefinition=N'@proid1int,@id1 int,@countOUT   int   output';

exec sp_executesql @SQLString,@ParmDefinition,@proid1=@proid,@id1=@id,@countOUT=@count   output;

select  @count;

 

 

@sqlstring :就是你要执行的sql语句字符串

@ParmDefinition: @sqlstring里边用到的参数在这里声明 输出的参数要加output 

sp_executesql:

第一个参数sqlstring 就是执行的sql字符串了

第二个参数@ParmDefinition是@sqlstring里边用到的参数在这里声明 输出的参数要加output 

最后的参数加output的参数是输出的参数(需要和外部的相对应的变量建立关联)

中间的参数就是@sqlstring 里边用到的参数(需要和外部的相对应的变量建立关联)

最后你可以 select 输出的参数 来查询(select @count)

 

注意:output并不是返回值,而是ref

 

 

例如:exec sp_executesql @sql,N'@散装数 decimal(20,3),@装箱数 decimal

(20,3),@整箱数 decimal(20,3),@objid int,@入库单号 varchar(50),@含税进货价 decimal(20,4),@入库库位 varchar(50),@批次 varchar(100),@产品明细编号 varchar(50),@到期日期 datetime,@入库备注 varchar(200),@质检数量 decimal(20,3),@uservarchar(50),@税率 decimal(12,3),@ip varchar(100)'

,@散装数,@装箱数,@整箱数,@objid,@入库单号,@含税进货价,@入库库位,@批次,@产品明细编号,@到期日期,@入库备注,@质检数量,@user,@税率,@ip,@生产日期

主键

    exec(N''ALTER TABLE logs..user_临时表1  ADD CONSTRAINT pk_user PRIMARY KEY(订单编号)'')

为列‘订单编号’新建一个主键,主键名称叫做‘pk_user’。注意这个主键名称和其他表的主键名称不能重复,主键信息存在于sys.indexes表中。

 

 

 

SET Transaction Isolation Level Read语法的四种情况

http://www.cnblogs.com/qanholas/archive/2012/01/04/2312152.html

 

 

@@ROWCOUNT

记录返回结果的返回行数 

 

Ex:

select 1 as xx union select 2 as xx unionselect 3

select @@ROWCOUNT as yy

result:

 

 

having COUNT(*)

having一般跟在group by 之后,执行记录组选择的一部分来工作的。where 则是执行所有数据来工作的。having要跟在groupby之后。

例如要查询出count(*)>1的数据,可用查询语句:

select id,count(*) from tb_test where ... group by id having count(*)>1

即可得到count(*)>1且按id分组的数据记录

 

 

REPLACE函数的使用

REPLACE
用第三个表达式替换第一个字符串表达式中出现的所有第二个给定字符串表达式。

参数
''string_replace1''

待搜索的字符串表达式。string_replace1可以是字符数据或二进制数据。

''string_replace2''

待查找的字符串表达式。string_replace2可以是字符数据或二进制数据。

''string_replace3''

替换用的字符串表达式。string_replace3可以是字符数据或二进制数据。

返回类型
如果 string_replace(1、2 或 3)是支持的字符数据类型之一,则返回字符数据。如果 string_replace(1、2 或 3)是支持的 binary 数据类型之一,则返回二进制数据。

 

 

LOCK_TIMEOUT (Transact-SQL)

 

SET LOCK_TIMEOUT 允许应用程序设置语句等待阻塞资源的最长时间。当一条语句等待的时间长度超过 LOCK_TIMEOUT 所设置的时间长度时,被锁住的语句将自动取消,并给应用程序返回一条错误消息。

 

@@LOCK_TIMEOUT(Transact-SQL),返回当前会话的当前锁定超时设置(毫秒)。

 

Example1:

SET LOCK_TIMEOUT 20000

SELECT @@LOCK_TIMEOUT AS [Lock Timeout];

GO

 

下面是结果集:

Lock Timeout

------------

1800 

 

 

Group by

GROUP BY 语句

GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。

 

我们拥有下面这个 "Orders" 表:

O_Id

OrderDate

OrderPrice

Customer

1

2008/12/29

1000

Bush

2

2008/11/23

1600

Carter

3

2008/10/05

700

Bush

4

2008/09/28

300

Bush

5

2008/08/06

2000

Adams

6

2008/07/21

100

Carter

正确:

SELECTCustomer,SUM(OrderPrice) FROM Orders

正确:

SELECTCustomer,OrderDate,SUM(OrderPrice) FROM Orders

GROUP BYCustomer,OrderDate

 

错误:

SELECTCustomer, OrderDate ,SUM(OrderPrice) FROM Orders

GROUP BYCustomer,OrderDate

也就是说,不能选择没有groupby的列。但是可以选择sum/count/max等函数新建列,拿sum为例:

SELECTCustomer,SUM(OrderPrice) FROM Orders返回六行数据,sum是对所有行进行求和。

SELECTCustomer,OrderDate,SUM(OrderPrice) FROM Orders

GROUP BYCustomer,OrderDate返回三行数据,sum是对每组进行求和。

 

Sum/count/max函数如果不与group by合用,计算的是整个表;如果与group by合用,计算的是每个分组。

 

 

日期处理

DateName()

获取日期的各个部分

SelectDatename(hour,GetDate())
Select Datename(minute,GetDate())
Select Datename(second,GetDate())
Select Datename(weekDay,GetDate())
Select Datename(week,GetDate())

注意获取日期只能获取到3,不能获取到03,想要获到20150203用如下方法:

 

select GETDATE() as '当前日期',

DateName(year,GetDate()) as '年',

DateName(month,GetDate()) as '月',

DateName(day,GetDate()) as '日',

DateName(dw,GetDate()) as '星期',

DateName(week,GetDate()) as '周数',

DateName(hour,GetDate()) as '时',

DateName(minute,GetDate()) as '分',

DateName(second,GetDate()) as '秒'

使用Convert()函数:


selectconvert(char(10)   , GetDate(),120) asDate

* 第3个参数就是用来设置日期类型数据的显示样式的,下面介绍几种样式的参数:

100   mmdd yyyy

101  mm/dd/yyyy

102  yyyy.mm.dd

103  dd/mm/yyyy

106   ddmm yyyy

108  hh:mi:ss(时间)

111  yyyy/mm/dd

112  yyyymmdd

120  yyyy-mm-dd

1SELECT CONVERT(varchar(100), GETDATE(),0) 05 9 2011 9:12AM
2 SELECT CONVERT(varchar(100),GETDATE(), 1) 05/09/11
3SELECT CONVERT(varchar(100),GETDATE(), 2) 11.05.09
4SELECT CONVERT(varchar(100),GETDATE(), 3) 09/05/11
5SELECT CONVERT(varchar(100),GETDATE(), 4) 09.05.11
6SELECT CONVERT(varchar(100),GETDATE(), 5) 09-05-11
7SELECT CONVERT(varchar(100),GETDATE(), 6) 09 05 11
8SELECT CONVERT(varchar(100),GETDATE(), 7) 05 09, 11
9SELECT CONVERT(varchar(100),GETDATE(), 8) 09:13:14
10SELECT CONVERT(varchar(100),GETDATE(), 9) 05 9 2011 9:13:14:670AM
11SELECT CONVERT(varchar(100),GETDATE(), 10) 05-09-11
12SELECT CONVERT(varchar(100),GETDATE(), 11) 11/05/09
13SELECT CONVERT(varchar(100),GETDATE(), 12) 110509
14SELECT CONVERT(varchar(100),GETDATE(), 13) 09 05 2011 09:13:14:670
15SELECT CONVERT(varchar(100),GETDATE(), 14) 09:13:14:670
16SELECT CONVERT(varchar(100),GETDATE(), 20) 2011-05-09 09:13:14
17SELECT CONVERT(varchar(100),GETDATE(), 21) 2011-05-09 09:13:14.670
18SELECT CONVERT(varchar(100),GETDATE(), 22) 05/09/11 9:15:33AM
19SELECT CONVERT(varchar(100),GETDATE(), 23) 2011-05-09
20SELECT CONVERT(varchar(100),GETDATE(), 24) 09:15:33
21SELECT CONVERT(varchar(100),GETDATE(), 25) 2011-05-09 09:15:33.140
22SELECT CONVERT(varchar(100),GETDATE(), 100) 05 9 2011 9:15AM
23SELECT CONVERT(varchar(100),GETDATE(), 101) 05/09/2011
24SELECT CONVERT(varchar(100),GETDATE(), 102) 2011.05.09
25SELECT CONVERT(varchar(100),GETDATE(), 103) 09/05/2011
26SELECT CONVERT(varchar(100),GETDATE(), 104) 09.05.2011
27SELECT CONVERT(varchar(100),GETDATE(), 105) 09-05-2011
28SELECT CONVERT(varchar(100),GETDATE(), 106) 09 05 2011
29SELECT CONVERT(varchar(100),GETDATE(), 107) 05 09, 2011
30SELECT CONVERT(varchar(100),GETDATE(), 108) 09:16:38
31SELECT CONVERT(varchar(100),GETDATE(), 109) 05 9 2011 9:16:38:543AM
32SELECT CONVERT(varchar(100),GETDATE(), 110) 05-09-2011
33SELECT CONVERT(varchar(100),GETDATE(), 111) 2011/05/09
34SELECT CONVERT(varchar(100),GETDATE(), 112) 20110509
35SELECT CONVERT(varchar(100),GETDATE(), 113) 09 05 2011 09:17:19:857
36SELECT CONVERT(varchar(100),GETDATE(), 114) 09:17:19:857
37SELECT CONVERT(varchar(100),GETDATE(), 120) 2011-05-09 09:17:19
38SELECT CONVERT(varchar(100),GETDATE(), 121) 2011-05-09 09:17:19.857
39SELECT CONVERT(varchar(100),GETDATE(), 126) 2011-05-09T09:17:19.857
40SELECT CONVERT(varchar(100),GETDATE(), 130) 6 ????? ??????? 1432 9:17:19:857AM
41SELECT CONVERT(varchar(100),GETDATE(), 131) 6/06/1432 9:17:19:857AM

截取字符串

http://www.cnblogs.com/yeminglong/archive/2011/10/15/2212967.html

SUBSTRING     (      expression     ,      start     ,      length      )   

substring() 
——任意位置取子串 

left() 
right() 
——左右两端取子串 

ltrim() 
rtrim() 
——截断空格,没有trim()。 

charindex() 
patindex() 

 

字符串大小写区分

select case when convert(varbinary, 'A')=convert(varbinary,'a') then 1 else 2 end

数据库表的写法:

数据库+权限+表名

如:logs.dbo.t400

1数据库省略默认当前数据库

2权限包括dbo/sys等,省略默认dbo,如logs..t400

3表名如果含有关键字,关键符号,首字符是数字等等,用[]括起来。


 

SQL异常处理 Begin try end try begin catch end catch

http://blog.csdn.net/wobuwei/article/details/4459019

 

事务

事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。

http://www.cnblogs.com/zhuifengnianshao/archive/2010/11/24/1886939.html

一般写法:

begin try

begin tran t1

commit tran t1

end try

begin catch

rollback tran t1

select ERROR_MESSAGE()errmsg

end catch

 

如果没有显示的执行rollback和try,当事务执行异常时不一定会自动回滚,需要设置SET XACT_ABORT,http://zhidao.baidu.com/link?url=k3CnIb_Apsa9j7jcXRnVNJpBHR8mftxbJYzDqGbkRd3_38lvVSdGla4pgPaOGphdO2Jg6OHGALBu7X0dnOvoIa

循环

while 条件
begin
执行操作
set @i=@i+1
end

 

实例:

declare @iint
set @i=1
while @i<30
begin
insert into test (userid) values(@i)
set @i=@i+1
end

 

Update 递归

利用变量与update逐行扫描的机制,实现逐行赋值。

例子一:

操作前#t

产品明细编号

仓库编号

实物库存

订货数量

分配后剩余

001

1

10

1

Null

001

1

10

2

Null

003

1

10

3

null

操作后#t

产品明细编号

仓库编号

实物库存

订货数量

分配后剩余

001

1

10

1

9

001

1

10

2

7

003

1

10

3

7

 代码如下:

select * into #t
from 
(select '001' 产品明细编号,'1' 仓库编号,'10' 实物库存,'1' 订货数量,null 分配后剩余
union all
select '001' 产品明细编号,'1' 仓库编号,'10' 实物库存,'2' 订货数量,null 分配后剩余
union all
select '001' 产品明细编号,'1' 仓库编号,'10' 实物库存,'3' 订货数量,null 分配后剩余 ) a


declare  @产品明细编号 varchar(100)
set @产品明细编号=''
declare @分配前剩余 int
set  @分配前剩余=0 
declare @分配后剩余 int 
set @分配后剩余=0
declare @仓库编号 varchar(100) 
set  @仓库编号=''


update  a
set @分配前剩余=case when @产品明细编号 <> 产品明细编号 or   @仓库编号  <> 仓库编号 then 实物库存  else @分配前剩余 end   


  ,@分配后剩余=@分配前剩余-订货数量


  ,@产品明细编号 = 产品明细编号


  ,@仓库编号 = 仓库编号


,分配后剩余=@分配后剩余


  ,@分配前剩余=@分配后剩余


from #t a


select *from #t


例子二:

一个订单下有几行数据,但是快递费只想在一个订单下的第一行显示,其他行显示为0
drop table #t
select * into #t
from
(select 's1' 订单编号,'10'  快递费
union all
select 's1' 订单编号,'10'  快递费
union all
select 's2' 订单编号,'20'  快递费
union all
select 's2' 订单编号,'20'  快递费
union all
select 's2' 订单编号,'20'  快递费
union all
select 's3' 订单编号,'30'  快递费) a
select * from #t

declare @订单编号 varchar(20),@快递费 varchar(20)
set @订单编号=''
set @快递费=''

update a set @快递费=case when @订单编号=a.订单编号 then '0' else a.快递费 end
,@订单编号=a.订单编号
,a.快递费=@快递费
from #t a
select * from #t

--PS,误区,采用以下方法将得不到想要的结果:
--declare @订单编号 varchar(20)
--set @订单编号=''
--
--update a set a.快递费=case when @订单编号=a.订单编号 then '0' else a.快递费 end
--,@订单编号=a.订单编号
--from #t a
--select * from #t

 

存储过程创建与修改脚本之不同

创建

USE [master]

GO

 

/****** Object:  StoredProcedure [dbo].[sp_T拦截逾期]   Script Date: 04/08/2015 10:26:21 ******/

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id= OBJECT_ID(N'[dbo].[sp_T拦截逾期]') AND type in (N'P', N'PC'))

DROP PROCEDURE [dbo].[sp_T拦截逾期]

GO

 

USE [master]—数据库名称

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIERON

GO

create procedure  [dbo].[sp_T拦截逾期]

(

@TemptbName varchar(100),

@outmsg varchar(max)output

)

as

//your sql

 

GO

exec [master].dbo.sp_ms_marksystemobject'sp_T拦截逾期

 

修改

USE [master]

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

ALTER procedure  [dbo].[sp_T拦截逾期]

(

@TemptbName varchar(100),

@outmsg varchar(max) output

)

as

---------------------------------------yoursql

 

存储过程的调用

declare  @message varchar(max)=''

exec sp_T拦截逾期 'tempdb..#tempdb_ac0018_tp', @message OUTPUT

 

sp_executesql使用方式

sql字符串中的输入变量的定义需要在@ParmDefinition中定义,输出变量也需要在输入中用output标明,与存储过程调用有些类似。

DECLARE@IntVariable int;

DECLARE @SQLStringnvarchar(500);

DECLARE@ParmDefinition nvarchar(500);

DECLARE @max_titlevarchar(30);

 

SET @IntVariable =197;

SET @SQLString =N'SELECT @max_titleOUT = max(JobTitle)

   FROMAdventureWorks2012.HumanResources.Employee

   WHERE BusinessEntityID = @level';

SET @ParmDefinition= N'@level tinyint, @max_titleOUT varchar(30) OUTPUT';

 

EXECUTEsp_executesql @SQLString  ,   @ParmDefinition ,  @level = @IntVariable,@max_titleOUT=@max_title OUTPUT;

SELECT @max_title;

 

 

 

SQLServer2005中查询语句的执行顺序
 
--1.from
--2.on
--3.outer(join)
--4.where
--5.group by
--6.cube|rollup
--7.having
--8.select
--9.distinct
--10.order by
--11.top

 

USE [mybase]

GO

 

ALTER TABLE [dbo].[USER_T0452]  WITH CHECK ADD  CONSTRAINT [FK_USER_T0452_USER_T0304] FOREIGNKEY([TC0013])

REFERENCES [dbo].[USER_T0304] ([TC0013])

GO

 

ALTER TABLE [dbo].[USER_T0452] CHECK CONSTRAINT[FK_USER_T0452_USER_T0304]

GO

 

意义是:当0452表中有tc0013=’ssl’的值时,不能删除0304中的tc0013=’ssl’行。

 

 

换行的字符写法:

 

 

 

第二部分  性能调优

索引

定义:索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引的方式与您使用书籍中的索引的方式很相似:它搜索索引以找到特定值,然后顺指针找到包含该值的行。

 

好处:当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。

 

索引缺点

1.索引需要占物理空间。

2.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。

索引优点

1.大大加快数据的检索速度;

2.创建唯一性索引,保证数据库表中每一行数据的唯一性;

3.加速表和表之间的连接;

4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。

•   按照存储方式分为:

       聚集索引

聚集索引是指,对表本身的数据存储进行排序,在插入、修改、删除时对效率影响比较大,且一个表只能有一个聚集索引。

       非聚集索引

非聚集索引是指,对表本身的数据不进行排序,索引存放在硬盘的另一个位置;

    http://kb.cnblogs.com/page/144409/

例子:
创建非聚集索引:
if not exists(select 1 from sysindexes where name='索引名称' and object_name(id)='表1')--每个库都有一个sysindexes存放索引信息,或者在sys.indexes 中查找索引信息也可
begin
create  NONCLUSTERED INDEX [索引名称] on 表1 
       ([字段1] asc,
[字段2] asc)
end
创建聚集索引:
if not exists(select 1 from tempdb.sys.indexes where name='索引名称')
begin
create index 索引名称 on 表明 (字段1)
end

•   按照维护与管理索引角度分为:

       唯一索引

唯一索引是指,确保索引列不包含重复的值,主键是唯一索引,但唯一索引不一定是主键(唯一索引可以为null值),唯一索引所在列强制限制不能插入重复记录;

       复合索引

如果在两上以上的列上创建一个索引,则称为复合索引;

       系统自动

系统自建的索引,使用PRIMARY KEY或UNIQUE约束时,会在表上自动创建一个惟一索引。

•   创建索引:

Createindex idx1 on table1(col1,col2,col3)

•   删除索引:

Dropindex idx1 on table1

 

索引使用原则:

监视性能

SET STATISTICS IO ON

SET STATISTICS time on

在运行语句前面加上这两个语句,可以查看运行io和时间消耗

 

死锁

根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

使用SQL Server的系统存储过程sp_who和sp_lock,可以查看当前数据库中的锁情况;进而根据objectID(@objID)(SQLServer 2005)/ object_name(@objID)(Sql Server 2000)可以查看哪个资源被锁

使用SET LOCK_TIMEOUT timeout_period(单位为毫秒)来设定锁请求超时

http://www.cnblogs.com/happyhippy/archive/2008/11/14/1333922.html

 

编译调试

查看sql语句执行时间

{查询-查询选项-高级里,有个SET STATISTICS TIME勾上,然后执行SQL,看消息,就有执行时间了}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赫曦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值