SQL Server-Transact_SQL

  经典短小代码收集
SQL code
   
   
create table tz2008_1_1(id int ,name varchar ( 50 ))
insert into tz2008_1_1 select 1 , ' a '
create table tz2008_1_2(id int ,name varchar ( 50 ))
insert into tz2008_1_2 select 2 , ' b '
create table tz2008_1_3(id int ,name varchar ( 50 ))
insert into tz2008_1_3 select 3 , ' c '


declare @sql varchar ( 8000 )
select @sql = isnull ( @sql + ' union all ' , '' ) + ' select * from [ ' + name + ' ] '
from sysobjects where xtype = ' u ' and name like ' tz2008% '
exec ( @sql )



模糊表名的联合查询..

 

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

SQL code
   
   
-- 查询表的默认值
if object_id ( ' tb ' ) is not null
drop table tb
go
create table tb(id int ,name varchar ( 50 ) default ' abc ' ,num int default 5 )
insert into tb(id) select 1
insert into tb select 1 , ' oo ' , 100
insert into tb(id,name) select 1 , ' oo '
go
declare @tbname varchar ( 50 )
set @tbname = ' tb ' -- 表名
select @tbname as tbname,c.name as colname, replace ( replace ( replace ( replace (b. [ text ] , ' ( ''' , '' ), ''' ) ' , '' ), ' (( ' , '' ), ' )) ' , '' ) as defaultvalue
from sysconstraints a join syscomments b on a.constid = b.id
join syscolumns c on a.id = c.id and a.colid = c.colid
where a.id = object_id ( @tbname ) and object_name (a.constid) like ' %df% '



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

 

SQL code
   
   
-- 存储过程语句查询
if object_id ( ' proc_ttt ' ) is not null
drop proc proc_ttt
go
create proc proc_ttt
as
select 1 union select 2
go

select [ text ] from syscomments
where id = object_id ( ' proc_ttt ' )


EXEC SP_HELPTEXT ' proc_ttt '

---------------------------------------------------------------------------------
 
SQL code
   
   

-- 通过身份证获得户籍
create function f_getcityfromcid ( @cid varchar ( 18 ))
returns varchar ( 50 )
as
begin

declare @acity varchar ( 1000 )
set @acity = ' ____,____,____,____,____,____,____,____,____,____,____,北京__,天津__,河北__,山西__,内蒙古_,____,____,____,____,____,辽宁__,吉林__,黑龙江_,____,____,____,____,____,____,____,上海__,江苏__,浙江__,安微__,福建__,江西__,山东__,____,____,____,河南__,湖北__,湖南__,广东__,广西__,海南__,____,____,____,重庆__,四川__,贵州__,云南__,西藏__,____,____,____,____,____,____,陕西__,甘肃__,青海__,宁夏__,新疆__,____,____,____,____,____,台湾__,____,____,____,____,____,____,____,____,____,香港__,澳门__,____,____,____,____,____,____,____,____,国外__, '


set @cid = upper ( @cid )

IF ( len ( @cid ) <> 18 OR patindex ( ' %[^0-9X]% ' , @cid ) > 0 )
RETURN ' 你小子骗我,这不是合法的身份证 '

IF substring ( @acity , cast ( left ( @cid , 2 ) as int ) * 5 + 1 , 4 ) = ''
RETURN ' 你小子骗我,这身份证的地区码不存在 '


RETURN ' 这小子是: ' + replace ( substring ( @acity , cast ( left ( @cid , 2 ) as int ) * 5 + 1 , 4 ), ' _ ' , '' )

end
go

select dbo.f_getcityfromcid( ' 32108519760502ttt9 ' )
/*
--------------------------------------------------
你小子骗我,这不是合法的身份证

(所影响的行数为 1 行)

*/
select dbo.f_getcityfromcid( ' 32108519****026**9 ' )
/*
--------------------------------------------------
这小子是:江苏

(所影响的行数为 1 行)


*/
drop function f_getcityfromcid

--------------------------------------------------------------------------------------
SQL code
   
   
-- 随机选择一个小于等于500的组合
declare @tb table (id int ,num int )
insert into @tb select 1 , 1000
insert into @tb select 2 , 100
insert into @tb select 3 , 500
insert into @tb select 4 , 200
insert into @tb select 5 , 200
insert into @tb select 6 , 50
insert into @tb select 7 , 150
insert into @tb select 8 , 80
insert into @tb select 9 , 70

declare @idtb table (id int )
declare @num int , @id int , @sum int
set @sum = 0
while @sum <> 500
begin
select top 1 @id = id, @num = num from @tb where num <= 500 order by newid ()
if @num = 500
insert into @idtb select @id
else
if not exists ( select 1 from @idtb where id = @id )
insert into @idtb select @id
select @sum = sum (num) from @tb where id in ( select id from @idtb )
if ( @sum > 500 )
begin
delete @idtb
end
end

select * from @tb where id in (
select id from @idtb )

 
-----------------------------------------------------------------------------------
 
 
SQL code
    
    

/*
标题:普通行列转换(version 2.0)
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-03-09
地点:广东深圳
说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法。

问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
想变成(得到如下结果):
姓名 语文 数学 物理
---- ---- ---- ----
李四 74 84 94
张三 74 83 93
-------------------
*/

create table tb(姓名 varchar ( 10 ) , 课程 varchar ( 10 ) , 分数 int )
insert into tb values ( ' 张三 ' , ' 语文 ' , 74 )
insert into tb values ( ' 张三 ' , ' 数学 ' , 83 )
insert into tb values ( ' 张三 ' , ' 物理 ' , 93 )
insert into tb values ( ' 李四 ' , ' 语文 ' , 74 )
insert into tb values ( ' 李四 ' , ' 数学 ' , 84 )
insert into tb values ( ' 李四 ' , ' 物理 ' , 94 )
go

-- SQL SERVER 2000 静态SQL,指课程只有语文、数学、物理这三门课程。(以下同)
select 姓名 as 姓名 ,
max ( case 课程 when ' 语文 ' then 分数 else 0 end ) 语文,
max ( case 课程 when ' 数学 ' then 分数 else 0 end ) 数学,
max ( case 课程 when ' 物理 ' then 分数 else 0 end ) 物理
from tb
group by 姓名

-- SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar ( 8000 )
set @sql = ' select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [ ' + 课程 + ' ] '
from ( select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名 '
exec ( @sql )

-- SQL SERVER 2005 静态SQL。
select * from ( select * from tb) a pivot ( max (分数) for 课程 in (语文,数学,物理)) b

-- SQL SERVER 2005 动态SQL。
declare @sql varchar ( 8000 )
select @sql = isnull ( @sql + ' ],[ ' , '' ) + 课程 from tb group by 课程
set @sql = ' [ ' + @sql + ' ] '
exec ( ' select * from (select * from tb) a pivot (max(分数) for 课程 in ( ' + @sql + ' )) b ' )

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

/*
问题:在上述结果的基础上加平均分,总分,得到如下结果:
姓名 语文 数学 物理 平均分 总分
---- ---- ---- ---- ------ ----
李四 74 84 94 84.00 252
张三 74 83 93 83.33 250
*/

-- SQL SERVER 2000 静态SQL。
select 姓名 姓名,
max ( case 课程 when ' 语文 ' then 分数 else 0 end ) 语文,
max ( case 课程 when ' 数学 ' then 分数 else 0 end ) 数学,
max ( case 课程 when ' 物理 ' then 分数 else 0 end ) 物理,
cast ( avg (分数 * 1.0 ) as decimal ( 18 , 2 )) 平均分,
sum (分数) 总分
from tb
group by 姓名

-- SQL SERVER 2000 动态SQL。
declare @sql varchar ( 8000 )
set @sql = ' select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [ ' + 课程 + ' ] '
from ( select distinct 课程 from tb) as a
set @sql = @sql + ' , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名 '
exec ( @sql )

-- SQL SERVER 2005 静态SQL。
select m. * , n.平均分 , n.总分 from
(
select * from ( select * from tb) a pivot ( max (分数) for 课程 in (语文,数学,物理)) b) m,
(
select 姓名 , cast ( avg (分数 * 1.0 ) as decimal ( 18 , 2 )) 平均分 , sum (分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名

-- SQL SERVER 2005 动态SQL。
declare @sql varchar ( 8000 )
select @sql = isnull ( @sql + ' , ' , '' ) + 课程 from tb group by 课程
exec ( ' select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (
' + @sql + ' )) b) m ,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名
' )

drop table tb

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

/*
问题:如果上述两表互相换一下:即表结构和数据为:
姓名 语文 数学 物理
张三 74  83  93
李四 74  84  94
想变成(得到如下结果):
姓名 课程 分数
---- ---- ----
李四 语文 74
李四 数学 84
李四 物理 94
张三 语文 74
张三 数学 83
张三 物理 93
--------------
*/

create table tb(姓名 varchar ( 10 ) , 语文 int , 数学 int , 物理 int )
insert into tb values ( ' 张三 ' , 74 , 83 , 93 )
insert into tb values ( ' 李四 ' , 74 , 84 , 94 )
go

-- SQL SERVER 2000 静态SQL。
select * from
(
select 姓名 , 课程 = ' 语文 ' , 分数 = 语文 from tb
union all
select 姓名 , 课程 = ' 数学 ' , 分数 = 数学 from tb
union all
select 姓名 , 课程 = ' 物理 ' , 分数 = 物理 from tb
) t
order by 姓名 , case 课程 when ' 语文 ' then 1 when ' 数学 ' then 2 when ' 物理 ' then 3 end

-- SQL SERVER 2000 动态SQL。
--
调用系统表动态生态。
declare @sql varchar ( 8000 )
select @sql = isnull ( @sql + ' union all ' , '' ) + ' select 姓名 , [课程] = ' + quotename (Name , '''' ) + ' , [分数] = ' + quotename (Name) + ' from tb '
from syscolumns
where name! = N ' 姓名 ' and ID = object_id ( ' tb ' ) -- 表名tb,不包含列名为姓名的其它列
order by colid asc
exec ( @sql + ' order by 姓名 ' )

-- SQL SERVER 2005 动态SQL。
select 姓名 , 课程 , 分数 from tb unpivot (分数 for 课程 in ( [ 语文 ] , [ 数学 ] , [ 物理 ] )) t

-- SQL SERVER 2005 动态SQL,同SQL SERVER 2000 动态SQL。

-- ------------------
/*

问题:在上述的结果上加个平均分,总分,得到如下结果:
姓名 课程 分数
---- ------ ------
李四 语文 74.00
李四 数学 84.00
李四 物理 94.00
李四 平均分 84.00
李四 总分 252.00
张三 语文 74.00
张三 数学 83.00
张三 物理 93.00
张三 平均分 83.33
张三 总分 250.00
------------------
*/

select * from
(
select 姓名 as 姓名 , 课程 = ' 语文 ' , 分数 = 语文 from tb
union all
select 姓名 as 姓名 , 课程 = ' 数学 ' , 分数 = 数学 from tb
union all
select 姓名 as 姓名 , 课程 = ' 物理 ' , 分数 = 物理 from tb
union all
select 姓名 as 姓名 , 课程 = ' 平均分 ' , 分数 = cast ((语文 + 数学 + 物理) * 1.0 / 3 as decimal ( 18 , 2 )) from tb
union all
select 姓名 as 姓名 , 课程 = ' 总分 ' , 分数 = 语文 + 数学 + 物理 from tb
) t
order by 姓名 , case 课程 when ' 语文 ' then 1 when ' 数学 ' then 2 when ' 物理 ' then 3 when ' 平均分 ' then 4 when ' 总分 ' then 5 end

drop table tb

----------------------------------------------------------------------------------------
 
  
  
   
   SQL code 
  
  
  
  
    
    

-- 按某一字段分组取最大(小)值所在行的数据
--
(爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开) 2007-10-23于浙江杭州)
/*

数据如下:
name val memo
a 2 a2(a的第二个值)
a 1 a1--a的第一个值
a 3 a3:a的第三个值
b 1 b1--b的第一个值
b 3 b3:b的第三个值
b 2 b2b2b2b2
b 4 b4b4
b 5 b5b5b5b5b5
*/
-- 创建表并插入数据:
create table tb(name varchar ( 10 ),val int ,memo varchar ( 20 ))
insert into tb values ( ' a ' , 2 , ' a2(a的第二个值) ' )
insert into tb values ( ' a ' , 1 , ' a1--a的第一个值 ' )
insert into tb values ( ' a ' , 3 , ' a3:a的第三个值 ' )
insert into tb values ( ' b ' , 1 , ' b1--b的第一个值 ' )
insert into tb values ( ' b ' , 3 , ' b3:b的第三个值 ' )
insert into tb values ( ' b ' , 2 , ' b2b2b2b2 ' )
insert into tb values ( ' b ' , 4 , ' b4b4 ' )
insert into tb values ( ' b ' , 5 , ' b5b5b5b5b5 ' )
go

-- 一、按name分组取val最大的值所在行的数据。
--
方法1:
select a. * from tb a where val = ( select max (val) from tb where name = a.name) order by a.name
-- 方法2:
select a. * from tb a where not exists ( select 1 from tb where name = a.name and val > a.val)
-- 方法3:
select a. * from tb a,( select name, max (val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
-- 方法4:
select a. * from tb a inner join ( select name , max (val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
-- 方法5
select a. * from tb a where 1 > ( select count ( * ) from tb where name = a.name and val > a.val ) order by a.name
/*
name val memo
---------- ----------- --------------------
a 3 a3:a的第三个值
b 5 b5b5b5b5b5
*/

-- 二、按name分组取val最小的值所在行的数据。
--
方法1:
select a. * from tb a where val = ( select min (val) from tb where name = a.name) order by a.name
-- 方法2:
select a. * from tb a where not exists ( select 1 from tb where name = a.name and val < a.val)
-- 方法3:
select a. * from tb a,( select name, min (val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
-- 方法4:
select a. * from tb a inner join ( select name , min (val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
-- 方法5
select a. * from tb a where 1 > ( select count ( * ) from tb where name = a.name and val < a.val) order by a.name
/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 1 b1--b的第一个值
*/

-- 三、按name分组取第一次出现的行所在的数据。
select a. * from tb a where val = ( select top 1 val from tb where name = a.name) order by a.name
/*
name val memo
---------- ----------- --------------------
a 2 a2(a的第二个值)
b 1 b1--b的第一个值
*/

-- 四、按name分组随机取一条数据。
select a. * from tb a where val = ( select top 1 val from tb where name = a.name order by newid ()) order by a.name
/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 5 b5b5b5b5b5
*/

-- 五、按name分组取最小的两个(N个)val
select a. * from tb a where 2 > ( select count ( * ) from tb where name = a.name and val < a.val ) order by a.name,a.val
select a. * from tb a where val in ( select top 2 val from tb where name = a.name order by val) order by a.name,a.val
select a. * from tb a where exists ( select count ( * ) from tb where name = a.name and val < a.val having Count ( * ) < 2 ) order by a.name
/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
a 2 a2(a的第二个值)
b 1 b1--b的第一个值
b 2 b2b2b2b2
*/

-- 六、按name分组取最大的两个(N个)val
select a. * from tb a where 2 > ( select count ( * ) from tb where name = a.name and val > a.val ) order by a.name,a.val
select a. * from tb a where val in ( select top 2 val from tb where name = a.name order by val desc ) order by a.name,a.val
select a. * from tb a where exists ( select count ( * ) from tb where name = a.name and val > a.val having Count ( * ) < 2 ) order by a.name
/*
name val memo
---------- ----------- --------------------
a 2 a2(a的第二个值)
a 3 a3:a的第三个值
b 4 b4b4
b 5 b5b5b5b5b5
*/
-- 七,如果整行数据有重复,所有的列都相同。
/*

数据如下:
name val memo
a 2 a2(a的第二个值)
a 1 a1--a的第一个值
a 1 a1--a的第一个值
a 3 a3:a的第三个值
a 3 a3:a的第三个值
b 1 b1--b的第一个值
b 3 b3:b的第三个值
b 2 b2b2b2b2
b 4 b4b4
b 5 b5b5b5b5b5
*/
-- 在sql server 2000中只能用一个临时表来解决,生成一个自增列,先对val取最大或最小,然后再通过自增列来取数据。
--
创建表并插入数据:
create table tb(name varchar ( 10 ),val int ,memo varchar ( 20 ))
insert into tb values ( ' a ' , 2 , ' a2(a的第二个值) ' )
insert into tb values ( ' a ' , 1 , ' a1--a的第一个值 ' )
insert into tb values ( ' a ' , 1 , ' a1--a的第一个值 ' )
insert into tb values ( ' a ' , 3 , ' a3:a的第三个值 ' )
insert into tb values ( ' a ' , 3 , ' a3:a的第三个值 ' )
insert into tb values ( ' b ' , 1 , ' b1--b的第一个值 ' )
insert into tb values ( ' b ' , 3 , ' b3:b的第三个值 ' )
insert into tb values ( ' b ' , 2 , ' b2b2b2b2 ' )
insert into tb values ( ' b ' , 4 , ' b4b4 ' )
insert into tb values ( ' b ' , 5 , ' b5b5b5b5b5 ' )
go

select * , px = identity ( int , 1 , 1 ) into tmp from tb

select m.name,m.val,m.memo from
(
select t. * from tmp t where val = ( select min (val) from tmp where name = t.name)
) m
where px = ( select min (px) from
(
select t. * from tmp t where val = ( select min (val) from tmp where name = t.name)
) n
where n.name = m.name)

drop table tb,tmp

/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 1 b1--b的第一个值

(2 行受影响)
*/
-- 在sql server 2005中可以使用row_number函数,不需要使用临时表。
--
创建表并插入数据:
create table tb(name varchar ( 10 ),val int ,memo varchar ( 20 ))
insert into tb values ( ' a ' , 2 , ' a2(a的第二个值) ' )
insert into tb values ( ' a ' , 1 , ' a1--a的第一个值 ' )
insert into tb values ( ' a ' , 1 , ' a1--a的第一个值 ' )
insert into tb values ( ' a ' , 3 , ' a3:a的第三个值 ' )
insert into tb values ( ' a ' , 3 , ' a3:a的第三个值 ' )
insert into tb values ( ' b ' , 1 , ' b1--b的第一个值 ' )
insert into tb values ( ' b ' , 3 , ' b3:b的第三个值 ' )
insert into tb values ( ' b ' , 2 , ' b2b2b2b2 ' )
insert into tb values ( ' b ' , 4 , ' b4b4 ' )
insert into tb values ( ' b ' , 5 , ' b5b5b5b5b5 ' )
go

select m.name,m.val,m.memo from
(
select * , px = row_number() over ( order by name , val) from tb
) m
where px = ( select min (px) from
(
select * , px = row_number() over ( order by name , val) from tb
) n
where n.name = m.name)

drop table tb

/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 1 b1--b的第一个值

(2 行受影响)
*/
  
  
------------------------------------------------------------------------------------------
 
合并列值
原著:邹建
改编:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)  2007-12-16  广东深圳

表结构,数据如下:
id    value
----- ------
1    aa
1    bb
2    aaa
2    bbb
2    ccc

需要得到结果:
id    values
------ -----------
1      aa,bb
2      aaa,bbb,ccc
即:group by id, 求 value 的和(字符串相加)

1. 旧的解决方法(在sql server 2000中只能用函数解决。)
--1. 创建处理函数
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

CREATE FUNCTION dbo.f_str(@id int)
RETURNS varchar(8000)
AS
BEGIN
    DECLARE @r varchar(8000)
    SET @r = ''
    SELECT @r = @r + ',' + value FROM tb WHERE id=@id
    RETURN STUFF(@r, 1, 1, '')
END
GO

-- 调用函数
SELECt id, value = dbo.f_str(id) FROM tb GROUP BY id

drop table tb
drop function dbo.f_str

/*
id          value     
----------- -----------
1          aa,bb
2          aaa,bbb,ccc
(所影响的行数为 2 行)
*/

--2、另外一种函数.
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

--创建一个合并的函数
create function f_hb(@id int)
returns varchar(8000)
as
begin
  declare @str varchar(8000)
  set @str = ''
  select @str = @str + ',' + cast(value as varchar) from tb where id = @id
  set @str = right(@str , len(@str) - 1)
  return(@str)
End
go

--调用自定义函数得到结果:
select distinct id ,dbo.f_hb(id) as value from tb

drop table tb
drop function dbo.f_hb

/*
id          value     
----------- -----------
1          aa,bb
2          aaa,bbb,ccc
(所影响的行数为 2 行)
*/

2. 新的解决方法(在sql server 2005中用OUTER APPLY等解决。)
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go
-- 查询处理
SELECT * FROM(SELECT DISTINCT id FROM tb)A OUTER APPLY(
        SELECT [values]= STUFF(REPLACE(REPLACE(
            (
                SELECT value FROM tb N
                WHERE id = A.id
                FOR XML AUTO
            ), ' <N value="', ','), '"/>', ''), 1, 1, '')
)N
drop table tb

/*
id          values
----------- -----------
1          aa,bb
2          aaa,bbb,ccc

(2 行受影响)
*/

--SQL2005中的方法2
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

select id, [values]=stuff((select ','+[value] from tb t where id=tb.id for xml path('')), 1, 1, '')
from tb
group by id

/*
id          values
----------- --------------------
1          aa,bb
2          aaa,bbb,ccc

(2 row(s) affected)

*/

drop table tb
----------------------------------------------------------------------------------------
 
分拆列值 

原著:邹建
改编:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)  2007-12-16  广东深圳

有表tb, 如下:
id          value
----------- -----------
1          aa,bb
2          aaa,bbb,ccc
欲按id,分拆value列, 分拆后结果如下:
id          value
----------- --------
1          aa
1          bb
2          aaa
2          bbb
2          ccc

1. 旧的解决方法(sql server 2000)
SELECT TOP 8000 id = IDENTITY(int, 1, 1) INTO # FROM syscolumns a, syscolumns b

SELECT A.id, SUBSTRING(A.[values], B.id, CHARINDEX(',', A.[values] + ',', B.id) - B.id)
FROM tb A, # B
WHERE SUBSTRING(',' + A.[values], B.id, 1) = ','

DROP TABLE #

2. 新的解决方法(sql server 2005)

create table tb(id int,value varchar(30))
insert into tb values(1,'aa,bb')
insert into tb values(2,'aaa,bbb,ccc')
go
SELECT A.id, B.value
FROM(
    SELECT id, [value] = CONVERT(xml,' <root> <v>' + REPLACE([value], ',', ' </v> <v>') + ' </v> </root>') FROM tb
)A
OUTER APPLY(
    SELECT value = N.v.value('.', 'varchar(100)') FROM A.[value].nodes('/root/v') N(v)
)B

DROP TABLE tb

/*
id          value
----------- ------------------------------
1          aa
1          bb
2          aaa
2          bbb
2          ccc

(5 行受影响)
*/
 
-------------------------------------------------------------------------------------------
 
  
  
   
   SQL code 
  
  
  
  
    
    

日期的推算:(转邹老大的代码)
DECLARE @dt datetime
SET @dt = GETDATE ()

DECLARE @number int
SET @number = 3

-- 1.指定日期该年的第一天或最后一天
--
A. 年的第一天
SELECT CONVERT ( char ( 5 ), @dt , 120 ) + ' 1-1 '

-- B. 年的最后一天
SELECT CONVERT ( char ( 5 ), @dt , 120 ) + ' 12-31 '


-- 2.指定日期所在季度的第一天或最后一天
--
A. 季度的第一天
SELECT CONVERT ( datetime ,
CONVERT ( char ( 8 ),
DATEADD ( Month ,
DATEPART (Quarter, @dt ) * 3 - Month ( @dt ) - 2 ,
@dt ),
120 ) + ' 1 ' )

-- B. 季度的最后一天(CASE判断法)
SELECT CONVERT ( datetime ,
CONVERT ( char ( 8 ),
DATEADD ( Month ,
DATEPART (Quarter, @dt ) * 3 - Month ( @dt ),
@dt ),
120 )
+ CASE WHEN DATEPART (Quarter, @dt ) in ( 1 , 4 )
THEN ' 31 ' ELSE ' 30 ' END )

-- C. 季度的最后一天(直接推算法)
SELECT DATEADD ( Day , - 1 ,
CONVERT ( char ( 8 ),
DATEADD ( Month ,
1 + DATEPART (Quarter, @dt ) * 3 - Month ( @dt ),
@dt ),
120 ) + ' 1 ' )


-- 3.指定日期所在月份的第一天或最后一天
--
A. 月的第一天
SELECT CONVERT ( datetime , CONVERT ( char ( 8 ), @dt , 120 ) + ' 1 ' )

-- B. 月的最后一天
SELECT DATEADD ( Day , - 1 , CONVERT ( char ( 8 ), DATEADD ( Month , 1 , @dt ), 120 ) + ' 1 ' )

-- C. 月的最后一天(容易使用的错误方法)
SELECT DATEADD ( Month , 1 , DATEADD ( Day , - DAY ( @dt ), @dt ))


-- 4.指定日期所在周的任意一天
SELECT DATEADD ( Day , @number - DATEPART (Weekday, @dt ), @dt )


-- 5.指定日期所在周的任意星期几
--
A. 星期天做为一周的第1天
SELECT DATEADD ( Day , @number - ( DATEPART (Weekday, @dt ) + @@DATEFIRST - 1 ) % 7 , @dt )

-- B. 星期一做为一周的第1天
SELECT DATEADD ( Day , @number - ( DATEPART (Weekday, @dt ) + @@DATEFIRST - 2 ) % 7 - 1 , @dt )


----------------------------------------------------------------------------------
 
SQL code
    
    

/*
标题:分解字符串并查询相关数据
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-03-18
地点:广东深圳
说明:通过使用函数等方法分解字符串查询相关数据。

问题:通过分解一个带某种符号分隔的字符串在数据库中查找相关数据。
例如 @str = '1,2,3',查询下表得到记录1,4,5,6
ID TypeID
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
6 6,7
*/
-- ---------------------------
create table tb (ID int , TypeID varchar ( 30 ))
insert into tb values ( 1 , ' 1,2,3,4,5,6,7,8,9,10,11,12 ' )
insert into tb values ( 2 , ' 2,3 ' )
insert into tb values ( 3 , ' 3,7,8,9 ' )
insert into tb values ( 4 , ' 2,6 ' )
insert into tb values ( 5 , ' 4,5 ' )
insert into tb values ( 6 , ' 6,7 ' )
go
-- ---------------------------
--
如果仅仅是一个,如@str = '1'.
declare @str as varchar ( 30 )
set @str = ' 1 '
select * from tb where charindex ( ' , ' + @str + ' , ' , ' , ' + TypeID + ' , ' ) > 0
select * from tb where ' , ' + TypeID + ' , ' like ' %, ' + @str + ' ,% '
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
(所影响的行数为 1 行)
*/

-- ---------------------------
--
如果包含两个,如@str = '1,2'.
declare @str as varchar ( 30 )
set @str = ' 1,2 '
select * from tb where charindex ( ' , ' + left ( @str , charindex ( ' , ' , @str ) - 1 ) + ' , ' , ' , ' + typeid + ' , ' ) > 0 or
charindex ( ' , ' + substring ( @str , charindex ( ' , ' , @str ) + 1 , len ( @str )) + ' , ' , ' , ' + typeid + ' , ' ) > 0
select * from tb where ' , ' + typeid + ' , ' like ' %, ' + left ( @str , charindex ( ' , ' , @str ) - 1 ) + ' ,% ' or
' , ' + typeid + ' , ' like ' %, ' + substring ( @str , charindex ( ' , ' , @str ) + 1 , len ( @str )) + ' ,% '
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
4 2,6
(所影响的行数为 3 行)
*/

-- -----------------------------------------
--
如果包含三个或四个,用PARSENAME函数来处理.
declare @str as varchar ( 30 )
set @str = ' 1,2,3,4 '
select * from tb where
charindex ( ' , ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 4 ) + ' , ' , ' , ' + typeid + ' , ' ) > 0 or
charindex ( ' , ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 3 ) + ' , ' , ' , ' + typeid + ' , ' ) > 0 or
charindex ( ' , ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 2 ) + ' , ' , ' , ' + typeid + ' , ' ) > 0 or
charindex ( ' , ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 1 ) + ' , ' , ' , ' + typeid + ' , ' ) > 0
select * from tb where
' , ' + typeid + ' , ' like ' %, ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 4 ) + ' ,% ' or
' , ' + typeid + ' , ' like ' %, ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 3 ) + ' ,% ' or
' , ' + typeid + ' , ' like ' %, ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 2 ) + ' ,% ' or
' , ' + typeid + ' , ' like ' %, ' + parsename ( replace ( @str , ' , ' , ' . ' ) , 1 ) + ' ,% '
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/

-- -------------------------------------
--
如果超过四个,则只能使用函数或动态SQL来分解并查询数据。
/*

名称:fn_split函数.
功能:实现字符串分隔功能的函数
*/
create function dbo.fn_split( @inputstr varchar ( 8000 ), @seprator varchar ( 10 ))
returns @temp table (a varchar ( 200 ))
as
begin
declare @i int
set @inputstr = rtrim ( ltrim ( @inputstr ))
set @i = charindex ( @seprator , @inputstr )
while @i >= 1
begin
insert @temp values ( left ( @inputstr , @i - 1 ))
set @inputstr = substring ( @inputstr , @i + 1 , len ( @inputstr ) - @i )
set @i = charindex ( @seprator , @inputstr )
end
if @inputstr <> ' / '
insert @temp values ( @inputstr )
return
end
go

-- 调用
declare @str as varchar ( 30 )
set @str = ' 1,2,3,4,5 '

select distinct m. * from tb m,
(
select * from dbo.fn_split( @str , ' , ' )) n
where charindex ( ' , ' + n.a + ' , ' , ' , ' + m.typeid + ' , ' ) > 0

drop table tb
drop function dbo.fn_split

/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/

-- ----------------------------------------
--
使用动态SQL的语句。
declare @str varchar ( 200 )
declare @sql as varchar ( 1000 )
set @str = ' 1,2,3,4,5 '
set @sql = ' select ''' + replace ( @str , ' , ' , ''' as id union all select ''' )
set @sql = @sql + ''''
set @sql = ' select distinct a.* from tb a , ( ' + @sql + ' ) b where charindex( ' + ''' , '' + b.id + ' + ''' , ''' + ' , ' + ''' , '' + a.typeid + ' + ''' , ''' + ' ) > 0 '
exec ( @sql )
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/


--------------------------------------------------------------------------------------------
 
  
  
   
   SQL code 
  
  
  
  
    
    

/* 本文由微软新闻组摘录下来的。一段非常有用的脚本。
如果碰到日志文件过大的问题,用SHIRNK DATABASE, TRUNCATE LOG FILE不是很有效时,可以考虑试下下面的脚本。把代码COPY到查询分析器里,然后修改其中的3个参数(数据库名,日志文件名,和目标日志文件的大小),运行即可
*/
-- --------------------------------------------------------------------------------
SET NOCOUNT ON
DECLARE @LogicalFileName sysname, -- 日志文件名
@MaxMinutes INT , -- 允许此脚本执行的最长时间
@NewSize INT -- 目标日志文件的大小


USE CRM -- 要操作的数据库名

SELECT @LogicalFileName = ' CRM_LOG ' , -- 日志文件名

@MaxMinutes = 10 , -- Limit on time allowed to wrap log.

@NewSize = 1 -- 想要收缩到的目标大小(单位M),此处标记收缩到1M

DECLARE @OriginalSize int

SELECT @OriginalSize = size
FROM sysfiles
WHERE name = @LogicalFileName

SELECT ' Original Size of ' + db_name () + ' LOG is ' +
CONVERT ( VARCHAR ( 30 ), @OriginalSize ) + ' 8K pages or ' +
CONVERT ( VARCHAR ( 30 ),( @OriginalSize * 8 / 1024 )) + ' MB '
FROM sysfiles
WHERE name = @LogicalFileName

CREATE TABLE DummyTrans(DummyColumn char ( 8000 ) not null )


DECLARE @Counter INT ,
@StartTime DATETIME ,
@TruncLog VARCHAR ( 255 )

SELECT @StartTime = GETDATE (),
@TruncLog = ' BACKUP LOG ' + db_name () + ' WITH TRUNCATE_ONLY '

DBCC SHRINKFILE ( @LogicalFileName , @NewSize )

EXEC ( @TruncLog )

-- Wrap the log if necessary.
WHILE @MaxMinutes > DATEDIFF (mi, @StartTime , GETDATE ()) -- time has not expired
AND @OriginalSize = ( SELECT size FROM sysfiles WHERE name =
@LogicalFileName )
AND ( @OriginalSize * 8 / 1024 ) > @NewSize

BEGIN -- Outer loop.
SELECT @Counter = 0

WHILE (( @Counter < @OriginalSize / 16 ) AND ( @Counter < 50000 ))
BEGIN -- update
INSERT DummyTrans VALUES ( ' Fill Log ' )
DELETE DummyTrans
SELECT @Counter = @Counter + 1
END

EXEC ( @TruncLog )

END

SELECT ' Final Size of ' + db_name () + ' LOG is ' +
CONVERT ( VARCHAR ( 30 ),size) + ' 8K pages or ' +
CONVERT ( VARCHAR ( 30 ),(size * 8 / 1024 )) + ' MB '
FROM sysfiles
WHERE name = @LogicalFileName

DROP TABLE DummyTrans

SET NOCOUNT OFF

----------------------------------------------------------------------------------------------
  
  
 
SQL code
     
     
-- 递归删除父节点及所有子节点
create table tb(Id int , ParentId int , Name varchar ( 5 ))
insert into tb select 1 , 0 , ' a1 '
union all select 2 , 2 , ' a2 '
union all select 14 , 1 , ' b11 '
union all select 15 , 1 , ' b12 '
union all select 16 , 14 , ' c13 '
union all select 17 , 14 , ' c14 '
union all select 104 , 17 , ' d15 '
go
WITH temptab(id, parentid, name) AS
(
SELECT root.id, root.parentid, root.name
FROM tb root
WHERE id = 1
UNION ALL
SELECT sub.id, sub.parentid, sub.name
FROM tb sub, temptab super
WHERE sub.parentid = super.id
)
delete from tb where id in (
select id from temptab
)
select * from tb
go
drop table tb
/*
Id ParentId Name
----------- ----------- -----
2 2 a2

 
-----------------------------------------------------------------------------------------------
 
精妙SQL语句 

明:复制表(只复制结构,源表名:a 新表名:b)
SQL: select * into b from a where 1 <>1

说明:拷贝表(拷贝数据,源表名:a 目标表名:b)
SQL: insert into b(a, b, c) select d,e,f from b;

说明:显示文章、提交人和最后回复时间
SQL: select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b

说明:外连接查询(表名1:a 表名2:b)
SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

说明:日程安排提前五分钟提醒
SQL: select * from 日程安排 where datediff( <|>minute <|>,f开始时间,getdate())>5


说明:两张关联表,删除主表中已经在副表中没有的信息
SQL:
delete from info where not exists ( select * from infobz where info.infid=infobz.infid )

说明:--
SQL:
SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE
FROM TABLE1,
(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE
FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND
FROM TABLE2
WHERE TO_CHAR(UPD_DATE, <|>YYYY/MM <|>) = TO_CHAR(SYSDATE, <|>YYYY/MM <|>)) X,
(SELECT NUM, UPD_DATE, STOCK_ONHAND
FROM TABLE2
WHERE TO_CHAR(UPD_DATE, <|>YYYY/MM <|>) =
TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, <|>YYYY/MM <|>) || <|>/01 <|>, <|>YYYY/MM/DD <|>) - 1, <|>YYYY/MM <|>) ) Y,
WHERE X.NUM = Y.NUM (+)
AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND ) B
WHERE A.NUM = B.NUM

说明:--
SQL:
select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and 系名称= <|>"&strdepartmentname&" <|> and 专业名称= <|>"&strprofessionname&" <|> order by 性别,生源地,高考总成绩

说明:
从数据库中去一年的各单位电话费统计(电话费定额贺电化肥清单两个表来源)
SQL:
SELECT a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, <|>yyyy <|>) AS telyear,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>01 <|>, a.factration)) AS JAN,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>02 <|>, a.factration)) AS FRI,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>03 <|>, a.factration)) AS MAR,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>04 <|>, a.factration)) AS APR,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>05 <|>, a.factration)) AS MAY,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>06 <|>, a.factration)) AS JUE,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>07 <|>, a.factration)) AS JUL,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>08 <|>, a.factration)) AS AGU,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>09 <|>, a.factration)) AS SEP,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>10 <|>, a.factration)) AS OCT,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>11 <|>, a.factration)) AS NOV,
SUM(decode(TO_CHAR(a.telfeedate, <|>mm <|>), <|>12 <|>, a.factration)) AS DEC
FROM (SELECT a.userper, a.tel, a.standfee, b.telfeedate, b.factration
FROM TELFEESTAND a, TELFEE b
WHERE a.tel = b.telfax) a
GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, <|>yyyy <|>)

说明:四表联查问题:
SQL: select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....

说明:得到表中最小的未使用的ID号
SQL:
SELECT (CASE WHEN EXISTS(SELECT * FROM Handle b WHERE b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID
FROM Handle
WHERE NOT HandleID IN (SELECT a.HandleID - 1 FROM Handle a)
 
-----------------------------------------------------------------------------------------------
 
 
不足5位数补零的方法 
public string getNumberString(int n)
{
    if(n.ToString().Length <5)
    {
        return (1000000+n).ToString().SubString(1);
    }
    return n.ToString();
}
 
--------------------------------------------------------------------------------------
 
ip各段内容提取,类似有3或4段字串通过一特殊字符连接的字串提取 
-----------------------------------
declare @a varchar(50)
set @a='192.168.1.123'
SELECT PARSENAME(@a,1),PARSENAME(@a,2),PARSENAME(@a,3),PARSENAME(@a,4)
set @a='100,200,300'
SELECT PARSENAME(replace(@a,',','.'),1)高,PARSENAME(replace(@a,',','.'),2)宽
,PARSENAME(replace(@a,',','.'),3)长
 
----------------------------------------------------------------------------------------------
 
--备份 
declare  @sql  varchar(8000) 
set  @sql='backup  database  mis    to  disk=''d:/databack/mis/mis' 
+rtrim(convert(varchar,getdate(),112))+'.bak''' 
exec(@sql)   
--删除15天前备份文件 
set  @sql='del  d:/databack/mis/mis' 
+rtrim(convert(varchar,getdate()-15,112))+'.bak''' 
exec  master..xp_cmdshell  @sql
 
-----------------------------------------------------------------------------------------------
 
求字串中所含某字符或某子串的个数 
declare @a varchar(100),@b varchar(20)
select @a='abcdefbcmnbcde',@b='bc'
select (len(@a)-len(replace(@a,@b,'')))/len(@b)
 
-----------------------------------------------------------------------------------------------
 
对查询结果进行随机排序 
select  * from dbo.Class order by newid()
 
-----------------------------------------------------------------------------------------------
 
*--比较两个数据库的表结构差异 

--*/
/*--调用示例

exec p_comparestructure 'xzkh_model','xzkh_new'
--*/

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_comparestructure]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_comparestructure]
GO

create proc p_comparestructure
@dbname1 varchar(250), --要比较的数据库名1
@dbname2 varchar(250) --要比较的数据库名2
as
create table #tb1(表名1 varchar(250),字段名 varchar(250),序号 int,标识 bit,主键 bit,类型 varchar(250),
占用字节数 int,长度 int,小数位数 int,允许空 bit,默认值 varchar(500),字段说明 varchar(500))

create table #tb2(表名2 varchar(250),字段名 varchar(250),序号 int,标识 bit,主键 bit,类型 varchar(250),
占用字节数 int,长度 int,小数位数 int,允许空 bit,默认值 varchar(500),字段说明 varchar(500))

--得到数据库1的结构
exec('insert into #tb1 SELECT
表名=d.name,字段名=a.name,序号=a.colid,
标识=case when a.status=0x80 then 1 else 0 end,
主键=case when exists(SELECT 1 FROM '+@dbname1+'..sysobjects where xtype=''PK'' and name in (
  SELECT name FROM '+@dbname1+'..sysindexes WHERE indid in(
  SELECT indid FROM '+@dbname1+'..sysindexkeys WHERE id = a.id AND colid=a.colid
  ))) then 1 else 0 end,
类型=b.name, 占用字节数=a.length,长度=a.prec,小数位数=a.scale, 允许空=a.isnullable,
默认值=isnull(e.text,''''''),字段说明=isnull(g.[value],'''''')
FROM '+@dbname1+'..syscolumns a
left join '+@dbname1+'..systypes b on a.xtype=b.xusertype
inner join '+@dbname1+'..sysobjects d on a.id=d.id  and d.xtype=''U'' and  d.name <>''dtproperties''
left join '+@dbname1+'..syscomments e on a.cdefault=e.id
left join '+@dbname1+'..sysproperties g on a.id=g.id and a.colid=g.smallid 
order by a.id,a.colorder')

--得到数据库2的结构
exec('insert into #tb2 SELECT
表名=d.name,字段名=a.name,序号=a.colid,
标识=case when a.status=0x80 then 1 else 0 end,
主键=case when exists(SELECT 1 FROM '+@dbname2+'..sysobjects where xtype=''PK'' and name in (
  SELECT name FROM '+@dbname2+'..sysindexes WHERE indid in(
  SELECT indid FROM '+@dbname2+'..sysindexkeys WHERE id = a.id AND colid=a.colid
  ))) then 1 else 0 end,
类型=b.name, 占用字节数=a.length,长度=a.prec,小数位数=a.scale, 允许空=a.isnullable,
默认值=isnull(e.text,''''''),字段说明=isnull(g.[value],'''''')
FROM '+@dbname2+'..syscolumns a
left join '+@dbname2+'..systypes b on a.xtype=b.xusertype
inner join '+@dbname2+'..sysobjects d on a.id=d.id  and d.xtype=''U'' and  d.name <>''dtproperties''
left join '+@dbname2+'..syscomments e on a.cdefault=e.id
left join '+@dbname2+'..sysproperties g on a.id=g.id and a.colid=g.smallid 
order by a.id,a.colorder')
--and not exists(select 1 from #tb2 where 表名2=a.表名1)
select 比较结果=case when a.表名1 is null and b.序号=1 then '库1缺少表:'+b.表名2
  when b.表名2 is null and a.序号=1 then '库2缺少表:'+a.表名1
  when a.字段名 is null and exists(select 1 from #tb1 where 表名1=b.表名2) then '库1 ['+b.表名2+'] 缺少字段:'+b.字段名
  when b.字段名 is null and exists(select 1 from #tb2 where 表名2=a.表名1) then '库2 ['+a.表名1+'] 缺少字段:'+a.字段名
  when a.标识 <>b.标识 then '标识不同'
  when a.主键 <>b.主键 then '主键设置不同'
  when a.类型 <>b.类型 then '字段类型不同'
  when a.占用字节数 <>b.占用字节数 then '占用字节数'
  when a.长度 <>b.长度 then '长度不同'
  when a.小数位数 <>b.小数位数 then '小数位数不同'
  when a.允许空 <>b.允许空 then '是否允许空不同'
  when a.默认值 <>b.默认值 then '默认值不同'
  when a.字段说明 <>b.字段说明 then '字段说明不同'
else '' end,
*
from #tb1 a
full join #tb2 b on a.表名1=b.表名2 and a.字段名=b.字段名
where a.表名1 is null or a.字段名 is null or b.表名2 is null or b.字段名 is null
or a.标识 <>b.标识 or a.主键 <>b.主键 or a.类型 <>b.类型
or a.占用字节数 <>b.占用字节数 or a.长度 <>b.长度 or a.小数位数 <>b.小数位数
or a.允许空 <>b.允许空 or a.默认值 <>b.默认值 or a.字段说明 <>b.字段说明
order by isnull(a.表名1,b.表名2),isnull(a.序号,b.序号)--isnull(a.字段名,b.字段名)
go
 
--------------------------------------------------------------------------------------------
 
  
  
   
   SQL code 
  
  
  
  
    
    

-- 查看数据库中所有的表
sp_MSforeachtable ' Select Top 1 * From ? '
-- 所有数据库的
sp_MSforeachdb

---------------------------------------------------------------------------------------------
 
SQL code
     
     
select @@version

----------------------------------------------------------------------------------------------
 
SQL code
     
     

-- 功能概述:重新编译一个表上的所有索引

alter index all on order_master rebuild

 
-----------------------------------------------------------------------------------------------
 
   
   
    
    SQL code 
   
   
   
   
     
     

-- 功能概述:显示某一表的结构

DECLARE @tableName nvarchar ( 100 )
SET @tableName = ' brand '

-- mssql2005
SELECT (
CASE WHEN a.colorder = 1 THEN d.name ELSE '' END )表名,
a.colorder 字段序号,
a.name 字段名,
(
CASE WHEN COLUMNPROPERTY ( a.id,a.name, ' IsIdentity ' ) = 1 THEN ' ' ELSE '' END ) 标识,
(
CASE WHEN (
SELECT COUNT ( * )
FROM sysobjects
WHERE (name IN
(
SELECT name
FROM sysindexes
WHERE (id = a.id) AND (indid IN
(
SELECT indid
FROM sysindexkeys
WHERE (id = a.id) AND (colid IN
(
SELECT colid
FROM syscolumns
WHERE (id = a.id) AND (name = a.name))))))) AND
(xtype
= ' PK ' )) > 0 THEN ' ' ELSE '' END ) 主键,
b.name 类型,
a.length 占用字节数,
COLUMNPROPERTY (a.id,a.name, ' PRECISION ' ) AS 长度,
ISNULL ( COLUMNPROPERTY (a.id,a.name, ' Scale ' ), 0 ) AS 小数位数,
(
CASE WHEN a.isnullable = 1 THEN ' ' ELSE '' END ) 允许空,
ISNULL (e. text , '' ) 默认值,
ISNULL (g. [ value ] , '' ) AS 字段说明
FROM syscolumns a
LEFT JOIN systypes b ON a.xtype = b.xusertype
INNER JOIN sysobjects d ON a.id = d.id AND d.xtype = ' U ' AND d.name <> ' dtproperties '
LEFT JOIN syscomments e ON a.cdefault = e.id
LEFT JOIN sys.extended_properties g ON a.id = g.major_id AND a.colid = g.major_id
WHERE d.name = @tableName
ORDER BY a.id,a.colorder
    
    
-----------------------------------------------------------------------------------------------
 
1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
法一:select * into b from a where 1 <>1
法二:select top 0 * into b from a

2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)
insert into b(a, b, c) select d,e,f from b;

3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)
insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件
例子:..from b in '"&Server.MapPath(".")&"/data.mdb" &"' where..

4、说明:子查询(表名1:a 表名2:b)
select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)

5、说明:显示文章、提交人和最后回复时间
select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b

6、说明:外连接查询(表名1:a 表名2:b)
select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c

7、说明:在线视图查询(表名1:a )
select * from (SELECT a,b,c FROM a) T where t.a > 1;

8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括
select * from table1 where time between time1 and time2
select a,b,c, from table1 where a not between 数值1 and 数值2

9、说明:in 的使用方法
select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)

10、说明:两张关联表,删除主表中已经在副表中没有的信息
delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )

11、说明:四表联查问题:
select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....

12、说明:日程安排提前五分钟提醒
SQL: select * from 日程安排 where datediff('minute',f开始时间,getdate())>5

13、说明:一条sql 语句搞定数据库分页
select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段

14、说明:前10条记录
select top 10 * form table1 where 范围

15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)
select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)

16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表
(select a from tableA ) except (select a from tableB) except (select a from tableC)

17、说明:随机取出10条数据
select top 10 * from tablename order by newid()

18、说明:随机选择记录
select newid()

19、说明:删除重复记录
Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)

20、说明:列出数据库里所有的表名
select name from sysobjects where type='U'

21、说明:列出表里的所有的
select name from syscolumns where id=object_id('TableName')

22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。
select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
显示结果:
type vender pcs
电脑 A 1
电脑 A 1
光盘 B 2
光盘 A 2
手机 B 3
手机 C 3

23、说明:初始化表table1
TRUNCATE TABLE table1

24、说明:选择从10到15的记录
select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
 
 
 
 
 
 
 
 
 
 
 
-----------------------------------------------------------------------------------------------
 

SQL code
       
       
-- 改变用户的锁定状态 (可适合一切 bit 类型的字段)

UPDATE tb_Table SET IsLook = Abs (IsLook - 1 ) WHERE Id = @id

-----------------------------------------------------------------------------------------------
 
/* 
08.09.20

知识点:SQL函数主要分为两中类型 1.单行函数(也叫标量函数) 2.多行函数
标量函数:对单一值操作,返回单一值。只要表达式有效即可使用标量函数。

我们把标量函数的分类列出来:
配置函数      返回当前配置信息
游标函数       返回游标信息
日期和时间函数  对日期和时间输入值进行操作,返回一个字符串、数字或日期和时间值
数学函数      对作为函数参数提供的输入值进行计算,返回一个数字值
元数据函数    返回有关数据库和数据库对象的信息
安全函数      返回有关用户和角色的信息
字符串函数    对字符串(char或varchar)输入值执行操作,返回一个字符串或数字值
系统函数      执行操作并返回有关Microsoft SQL Server中的值、对象和设置的信息
系统统计函数  返回系统的统计信息
文本和图象函数  对文本或图象进行操作并返回有关信息

聚合函数 是对一组值进行操作,跟标量函数不同.
行集函数 是可以向SQL语句中表引用一样使用,具体看文档了....
下面具体看例子了
*/

select emp_id,UPPER(lname),job_id
from employee
where lname='chang'
/*大小写处理函数*/
select emp_id,LOWER(lname),job_id
from employee
where lname='chang'

select emp_id,fname+lname NAME,  /*使用字符处理函数*/
job_id,LEN(lname) Length,
CHARINDEX('a',lname)"Contains 'a'?"
from employee
where SUBSTRING(emp_id,1,2)='MA'
/*
运算符 + :连接值在一起
substring :选取给定位置和长度的子字符串
len  :以数字值显示一个字符串的长度
charIndex  :找到一个给定字符的数字位置
Replicate  :用给定的字符替换给定长度的字符串
Ltrim和Rtrim  :从一个字符串中去除头或尾的字符
*/

select ROUND(2008.092023,2),/*数字函数ROUND四舍五入*/
ROUND(2008.092023,0),
ROUND(2008.092023,-1)
/*注意奇数偶数的进位不同 它也可以用语日期函数处理*/

select lname,job_lvl,job_lvl%50/*使用%(模)函数 经常用与确定一个值是奇数还是偶数*/
from employee
where job_lvl=5

select lname,hire_date/*日期的使用*/
from employee
where lname like 'A%'

select lname,hire_date+365 AS "One Year"/*用日期做算术运算 该例显示所有job_id=10的雇员的名字和其受雇满一年的日期*/
from employee
where job_id=10

select lname,  /*CONVERT函数用于日期转换*/
CONVERT(varchar(10),hire_date,20)
AS HIREDATE
from employee

select SUBSTRING(title,1,30) AS Title,ytd_sales/*对数字使用CAST函数*/
from titles
where CAST(ytd_sales AS char(20)) LIKE '3%'
/*
检索书名:这些图书的截止当前销售额的第一数字为3,并将这些图书的ytd_sales转换为char(20)
CAST(number,数据类型)
*/

select CONVERT(varchar(10),price,0) PRICE/*对数字使用CONVERT函数*/
from titles
where title_id='BU1111'

select CAST('2008-09-20 23:57' AS datetime)
/*使用CAST或CONVERT函数转换字符串到日期*/
select CONVERT(datetime,'2008-09-20 23:59')

select title,ytd_sales/*使用带有LIKE子句的CAST*/
from titles
where
CAST(ytd_sales AS char(20)) LIKE '15%'
AND type='trad_cook'

select title,ISNULL(price,0) Price,/*使用ISNULL函数*/
ISNULL(price*12,0) 'Ten Price'
from titles
/*为了计算所有图书的价格,在进行算术运算之前必须转换空值为一个数,ISNULL函数用来转换空值为零*/


select                      /*使用CASE表达式*/
CASE
when price IS NULL THEN 'Not yet priced'
when price <10 THEN 'Very Reasonable Title'
when price>=10 and price <20 THEN 'Coffee Table Title'
else 'Expensive book!'
END AS 'Price Category',  /*这个逗号不敢忘*/
CONVERT(varchar(20),title) AS "shorttened Title"
from pubs.dbo.titles
ORDER BY price
/*
使用CASE表达式使得if-then-else条件判断很容易实现
*/



select          /*使用CASE处理条件数据*/
CASE type
when 'popular_comp' then 'Popular Computing'
when 'mod_cook' then 'Modern Coking'
        when 'business' then 'Business'
when 'psychology' then 'Psychology'
when 'trad_cook' then 'Traditional Cooking'
else 'Not yet categorized'
END AS Category,
CONVERT(varchar(30),titles) AS "Shortened Title",
Price AS price
from titles
where price IS NOT NULL
ORDER BY 1


/*
小结下:掌握用函数对数据的计算
用函数修饰不同的数据项
用函数改变数据格式
用函数改变列数据类型
使用ISNULL函数
使用if-then-else逻辑
*/
/*最后一个例子有问题先不管了掌握语法就OK*/
 
-----------------------------------------------------------------------------------------------
 
SQL code
      
      
/* 08.09.20 */

select * from employee

use master /* 显示表结构 */
exec sp_helpdb
GO

use pubs
exec sp_help
GO

use pubs
exec sp_help employee
GO

select lname,job_lvl
from employee
where job_lvl <= 50

select lname,job_lvl /* 使用BETWEEN条件 */
from employee
where job_lvl BETWEEN 100 AND 200

select lname,job_id,job_lvl /* 使用IN成员条件测试在列表中的值 */
from employee
where job_lvl IN ( 100 , 170 , 200 )

select emp_id,lname,job_id,job_lvl /* 使用NOT操作 */
from employee
where job_lvl NOT IN ( 100 , 170 , 200 )

select title_id,title,type,price
from titles
where price IS NULL

select lname,job_lvl,job_lvl /* 优先规则AND在前 */
from employee
where job_lvl = 5
OR job_lvl = 7
AND job_lvl > 160

select lname,job_lvl,job_lvl /* 用圆括号强制优先权 */
from employee
where (job_lvl = 5
OR job_lvl = 7 )
AND job_lvl > 160

select lname,job_id,job_lvl,hire_date /* 用ORDER BY子句进行排序(升序排列) */
from employee
ORDER BY hire_date

select lname,job_id,job_lvl,hire_date /* 用DESC降序排列 */
from employee
ORDER BY hire_date DESC

select emp_id,lname,job_lvl * 2 " Double job_lvl" /* 用列别名排序 */
from employee
ORDER BY " Double job_lvl"

select lname,job_id,job_lvl /* 多列排序 */
from employee
ORDER BY job_id,job_lvl DESC

/*
小结下:主要掌握WHERE子句限制输出行
使用比较条件
使用BETWEEN,IN,AND,NOT,OR操作
最后掌握使用ORDER BY子句排序输出行
所有操作在数据库pubs里进行
*/

-----------------------------------------------------------------------------------------------
 
SQL code
    
    

/*
标题:日期分表查询(version 1.0)
网名:悬崖边的舞者
时间:2008-07-14
地点:天津
说明:以日期或月份分表进行多日、多月查询连表查询的有关写法
*/

Create Procedure Search
@date1 datetime , -- 起始时间
@date2 datetime -- 终止时间
as
declare @date1New datetime ,
@rq varchar ( 6 ),
@i int , -- 记录循环次数
@s varchar ( 5000 ) -- 根据表多少 可以扩大它
set @rq = convert ( varchar , @date1 , 12 ) -- 把时间格式化 比如2008-06-20 变成了080620


set @s = ' select * from sensor ' + @rq -- 初始化 @s='select * from sensor080620' 这样第一个表就有了

set @i = datediff (d, @date1 , @date2 ) -- 日期相减

while @i > 0
begin
-- 如果是非常重要的系统可以在这里加上该物理表是否存在的语句
--
if exists(select * from dbo.sysobjects where
--
id = object_id(N'c') and OBJECTPROPERTY(id,N'IsUserTable')=1)
--
begin
--
SELECT '存在 '
--
end

set @date1New = dateadd ( day , @i , @date1 )
set @rq = convert ( varchar , @date1New , 12 )
-- 如果是按月进行查询 就修改上面
set @s = @s + ' union all select * from sensor ' + @rq
set @i = @i - 1 -- 累加
end

select @s
-- exec(@S)
go


exec Search ' 2008-06-20 00:11:11.000 ' , ' 2008-07-25 00:11:11.000 '
drop Procedure Search



-----------------------------------------------------------------------------------------------
 
    
    
     
     SQL code 
    
    
    
    
      
      
create table tb(id varchar ( 3 ) , pid varchar ( 3 ) , name varchar ( 10 ))
insert into tb values ( ' 001 ' , null , ' 广东省 ' )
insert into tb values ( ' 002 ' , ' 001 ' , ' 广州市 ' )
insert into tb values ( ' 003 ' , ' 001 ' , ' 深圳市 ' )
insert into tb values ( ' 004 ' , ' 002 ' , ' 天河区 ' )
insert into tb values ( ' 005 ' , ' 003 ' , ' 罗湖区 ' )
insert into tb values ( ' 006 ' , ' 003 ' , ' 福田区 ' )
insert into tb values ( ' 007 ' , ' 003 ' , ' 宝安区 ' )
insert into tb values ( ' 008 ' , ' 007 ' , ' 西乡镇 ' )
insert into tb values ( ' 009 ' , ' 007 ' , ' 龙华镇 ' )
insert into tb values ( ' 010 ' , ' 007 ' , ' 松岗镇 ' )
go

-- 查询指定节点及其所有子节点的函数
create function f_cid( @ID varchar ( 3 )) returns @t_level table (id varchar ( 3 ) , level int )
as
begin
declare @level int
set @level = 1
insert into @t_level select @id , @level
while @@ROWCOUNT > 0
begin
set @level = @level + 1
insert into @t_level select a.id , @level
from tb a , @t_Level b
where a.pid = b.id and b. level = @level - 1
end
return
end
go

-- 调用函数查询001(广东省)及其所有子节点
select a. * from tb a , f_cid( ' 001 ' ) b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
001 NULL 广东省
002 001 广州市
003 001 深圳市
004 002 天河区
005 003 罗湖区
006 003 福田区
007 003 宝安区
008 007 西乡镇
009 007 龙华镇
010 007 松岗镇

(所影响的行数为 10 行)
*/

-- 调用函数查询002(广州市)及其所有子节点
select a. * from tb a , f_cid( ' 002 ' ) b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
002 001 广州市
004 002 天河区

(所影响的行数为 2 行)
*/

-- 调用函数查询003(深圳市)及其所有子节点
select a. * from tb a , f_cid( ' 003 ' ) b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
003 001 深圳市
005 003 罗湖区
006 003 福田区
007 003 宝安区
008 007 西乡镇
009 007 龙华镇
010 007 松岗镇

(所影响的行数为 7 行)
*/

drop table tb
drop function f_cid
     
     
 
-----------------------------------------------------------------------------------------------
 
 
SQL code
        
        
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER trigger [ tri_updatesalary_Mem_Type ]
on [ dbo ] . [ SalaryIncrease ]
after
insert
as
declare @i int
set @i = @@identity

update m
set m.Mem_Type = case when s.SMark > 500000 then ' 退休会员 ' -- 500000
when s.SMark > 400000 then ' 钻石五级 ' -- 400000
when s.SMark > 300000 then ' 钻石四级 ' -- 300000
when s.SMark > 200000 then ' 钻石三级 ' -- 200000
when s.SMark > 100000 then ' 钻石二级 ' -- 100000
when s.SMark > 50000 then ' 钻石一级 ' -- 50000
when s.SMark > 40000 then ' 五星级 ' -- 40000
when s.SMark > 30000 then ' 四星级 ' -- 30000
when s.SMark > 20000 then ' 三星级 ' -- 20000
when s.SMark > 10000 then ' 二星级 ' -- 10000
when s.SMark > 5000 then ' 一星级 ' -- 5000
else ' 一般VIP会员 '
end
from MemberInfo m
join ( select s.SCardName, sum (s.SMark) as SMark
from SalaryIncrease s join inserted i on s.SCardName = i.SCardName group by s.SCardName) s
on m.Mem_Num = s.SCardName

-- if exists(select * from MemberInfo m join inserted i on m.Mem_Num=i.SCardName and m.Mem_Mark>100 )
if exists ( select m.SCardName, sum (m.ShopMark) as mark from ( select m.SCardName,m.ShopMark from ShoppingMark m join inserted i on m.SCardName = i.SCardName
where year (m.SDate) = year ( getdate ()) and month (m.SDate) = month ( getdate ())) m
group by m.SCardName having sum (m.ShopMark) > 100 )
/**/
/* --最新的(我写的,上面是整合魅影的)select * from ShoppingMark SM join (select m.SCardName,sum(m.ShopMark) as Mark from ShoppingMark m join inserted i on m.SCardName=i.SCardName group by m.SCardName) s
on SM.SCardName=s.ScardName where month(SDate)=month(getdate()) and year(SDate)=year(getdate()) and s.Mark>100
*/
begin
update s
set s.SIncease = case
-- 积分大于1000就是星级.所以不用判断是否是星级
when m.Mem_Type <> ' 一般VIP会员 ' then s.SMark * 0.3
else case
when s.SMark > 4000 then
s.SMark
* 0.3
-- when s.SMark>4000 then
-- 200*0.2+200*0.23+200*0.25+200*0.28+(s.SMark-800)*0.3
when s.SMark > 3000 then
1000 * 0.2 + 1000 * 0.23 + 1000 * 0.25 + (s.SMark - 600 ) * 0.28
when s.SMark > 2000 then
1000 * 0.2 + 100 * 0.23 + (s.SMark - 400 ) * 0.25
when s.SMark > 1000 then
(s.SMark
- 200 ) * . 023 + 1000 * 0.2
else s.SMark * 0.2
end
end
from SalaryIncrease as s
join inserted i
on s.SCardName = i.SCardName
join MemberInfo m
on (i.SCardName = m.Mem_Num and s.SID = @i ) or (i.SCardName = m.Mem_Num and s.SIncease = 0 )
end
-- go
 
 
-----------------------------------------------------------------------------------------------
 
      
      
       
       SQL code 
      
      
      
      
        
        

-- bom结构,查找节点下所有子节点:

create table os(id int ,parentid int ,desn varchar ( 10 ))
insert into os select 1 , 0 , ' 体育用品 '
insert into os select 2 , 0 , ' 户外运动 '
insert into os select 3 , 1 , ' 篮球 '
insert into os select 4 , 1 , ' 足球 '
insert into os select 5 , 2 , ' 帐篷 '
insert into os select 6 , 2 , ' 登山鞋 '
insert into os select 7 , 0 , ' 男士用品 '
insert into os select 8 , 7 , ' 刮胡刀 '
insert into os select 9 , 3 , ' 大号篮球 '

-- 求个节点下所有子节点:
create function f_cid( @id int )
returns varchar ( 500 )
as
begin
declare @t table (id int ,parentid int ,desn varchar ( 10 ),lev int )
declare @lev int
set @lev = 1
insert into @t select * , @lev from os where id = @id
while ( @@rowcount > 0 )
begin
set @lev = @lev + 1
insert into @t select a. * , @lev from os a, @t b
where a.parentid = b.id and b.lev = @lev - 1
end
declare @cids varchar ( 500 )
select @cids = isnull ( @cids + ' , ' , '' ) + ltrim (id) from @t order by lev
return @cids
end
go

-- 调用函数
select * ,ids = dbo.f_cid(id) from os


-- 得到每个节点路径:
create proc wsp2
@id int
as
select * , cast ( ' ' as varchar ( 10 )) fullpath into #os from os
DECLARE @i int , @j int
set @i = 0
set @j = 1
select @i = max (parentid) from #os
update #os set fullpath = id
while @j <= @i
begin
update #os set fullpath = a.fullpath + ' , ' + ltrim (#os.id)
from #os inner join #os a on #os.parentid = a.id
where #os.parentid = @j
set @j = @j + 1
end
select * from #os
go
-- 调用存储过程
exec wsp2 1
       
       
-----------------------------------------------------------------------------------------------
 
1. 查看数据库的版本
select @@version

2. 查看数据库所在机器操作系统参数
exec master..xp_msver

3. 查看数据库启动的参数
sp_configure

4. 查看数据库启动时间
select convert(varchar(30),login_time,120) from master..sysprocesses where spid=1

查看数据库服务器名和实例名
print 'Server Name...............: ' + convert(varchar(30),@@SERVERNAME)
print 'Instance..................: ' + convert(varchar(30),@@SERVICENAME)
5. 查看所有数据库名称及大小
sp_helpdb

重命名数据库用的SQL
sp_renamedb 'old_dbname', 'new_dbname'

6. 查看所有数据库用户登录信息
sp_helplogins

查看所有数据库用户所属的角色信息
sp_helpsrvrolemember

修复迁移服务器时孤立用户时,可以用的fix_orphan_user脚本或者LoneUser过程

更改某个数据对象的用户属主
sp_changeobjectowner [@objectname =] 'object', [@newowner =] 'owner'

注意: 更改对象名的任一部分都可能破坏脚本和存储过程。

把一台服务器上的数据库用户登录信息备份出来可以用add_login_to_aserver脚本

7. 查看链接服务器
sp_helplinkedsrvlogin

查看远端数据库用户登录信息
sp_helpremotelogin

8.查看某数据库下某个数据对象的大小
sp_spaceused @objname

还可以用sp_toptables过程看最大的N(默认为50)个表

查看某数据库下某个数据对象的索引信息
sp_helpindex @objname

还可以用SP_NChelpindex过程查看更详细的索引情况
SP_NChelpindex @objname

clustered索引是把记录按物理顺序排列的,索引占的空间比较少。
对键值DML操作十分频繁的表我建议用非clustered索引和约束,fillfactor参数都用默认值。
查看某数据库下某个数据对象的的约束信息
sp_helpconstraint @objname

9.查看数据库里所有的存储过程和函数
use @database_name
sp_stored_procedures
查看存储过程和函数的源代码
sp_helptext '@procedure_name'

查看包含某个字符串@str的数据对象名称
select distinct object_name(id) from syscomments where text like '%@str%'

创建加密的存储过程或函数在AS前面加WITH ENCRYPTION参数

解密加密过的存储过程和函数可以用sp_decrypt过程

10.查看数据库里用户和进程的信息
sp_who
查看SQL Server数据库里的活动用户和进程的信息
sp_who 'active'
查看SQL Server数据库里的锁的情况
sp_lock

进程号1--50是SQL Server系统内部用的,进程号大于50的才是用户的连接进程.
spid是进程编号,dbid是数据库编号,objid是数据对象编号
查看进程正在执行的SQL语句
dbcc inputbuffer ()

推荐大家用经过改进后的sp_who3过程可以直接看到进程运行的SQL语句
sp_who3

检查死锁用sp_who_lock过程
sp_who_lock

11.收缩数据库日志文件的方法
收缩简单恢复模式数据库日志,收缩后@database_name_log的大小单位为M
backup log @database_name with no_log
dbcc shrinkfile (@database_name_log, 5)
12.分析SQL Server SQL 语句的方法:

set statistics time {on | off}
set statistics io {on | off}
图形方式显示查询执行计划

在查询分析器->查询->显示估计的评估计划(D)-Ctrl-L 或者点击工具栏里的图形

文本方式显示查询执行计划
set showplan_all {on | off}

set showplan_text { on | off }
set statistics profile { on | off }

13.出现不一致错误时,NT事件查看器里出3624号错误,修复数据库的方法

先注释掉应用程序里引用的出现不一致性错误的表,然后在备份或其它机器上先恢复然后做修复操作

alter database [@error_database_name] set single_user

修复出现不一致错误的表

dbcc checktable('@error_table_name',repair_allow_data_loss)

或者可惜选择修复出现不一致错误的小型数据库名

dbcc checkdb('@error_database_name',repair_allow_data_loss)
alter database [@error_database_name] set multi_user
CHECKDB 有3个参数:
repair_allow_data_loss 包括对行和页进行分配和取消分配以改正分配错误、结构行或页的错误,
以及删除已损坏的文本对象,这些修复可能会导致一些数据丢失。
修复操作可以在用户事务下完成以允许用户回滚所做的更改。
如果回滚修复,则数据库仍会含有错误,应该从备份进行恢复。
如果由于所提供修复等级的缘故遗漏某个错误的修复,则将遗漏任何取决于该修复的修复。
修复完成后,请备份数据库。
repair_fast 进行小的、不耗时的修复操作,如修复非聚集索引中的附加键。
这些修复可以很快完成,并且不会有丢失数据的危险。
repair_rebuild 执行由 repair_fast 完成的所有修复,包括需要较长时间的修复(如重建索引)。
执行这些修复时不会有丢失数据的危险。


以上脚本来源于:  http://www.51windows.net/data/files/file_797.asp 
 
-----------------------------------------------------------------------------------------------
 
SQL code
           
           

-- 库存先进先出简单例子:

create table t(
id
int identity ( 1 , 1 ),
name
varchar ( 50 ), -- 商品名称
j int , -- 入库数量
c int , -- 出库数量
jdate datetime -- 入库时间
)
insert into t(name,j,c,jdate) select ' A ' , 100 , 0 , ' 2007-12-01 '
insert into t(name,j,c,jdate) select ' A ' , 200 , 0 , ' 2008-01-07 '
insert into t(name,j,c,jdate) select ' B ' , 320 , 0 , ' 2007-12-21 '
insert into t(name,j,c,jdate) select ' A ' , 100 , 0 , ' 2008-01-15 '
insert into t(name,j,c,jdate) select ' B ' , 90 , 0 , ' 2008-02-03 '
insert into t(name,j,c,jdate) select ' A ' , 460 , 0 , ' 2008-02-01 '
insert into t(name,j,c,jdate) select ' A ' , 510 , 0 , ' 2008-03-01 '
go



create proc wsp
@name varchar ( 50 ), -- 商品名称
@cost int -- 销售量
as
-- 先得出该货物的库存是否够
declare @spare float -- 剩余库存
select @spare = sum (j) - sum (c) from t where name = @name
if ( @spare >= @cost )
begin
-- 根据入库日期采用先进先出原则对货物的库存进行处理
update t set c =
case when ( select @cost - isnull ( sum (j), 0 ) + isnull ( sum (c), 0 ) from t where name = @name and jdate <= a.jdate and j != c) >= 0
then a.j
else
case when ( select @cost - isnull ( sum (j), 0 ) + isnull ( sum (c), 0 ) from t where name = @name and jdate < a.jdate and j != c) < 0 then 0
else ( select @cost - isnull ( sum (j), 0 ) + isnull ( sum (c), 0 ) + a.c from t where name = @name and jdate < a.jdate and j != c)
end
end
from t a where name = @name and j != c
end
else
raiserror ( ' 库存不足 ' , 16 , 1 )
return
go


-- 测试:

exec wsp @name = ' A ' , @cost = 180
select * from t


-- drop table t
--
drop proc wsp
 
-----------------------------------------------------------------------------------------------
 
SQL code
       
       
-- 返程问题,找出雇员从本地出发后直接返回的情况
create table trav(name nvarchar ( 10 ),date datetime ,comefrom nvarchar ( 10 ),destin nvarchar ( 10 ),id int )
insert into trav select ' 张三 ' , ' 2007-01-01 ' , ' 上海 ' , ' 广州 ' , 1
insert into trav select ' 李四 ' , ' 2007-01-01 ' , ' 上海 ' , ' 广州 ' , 2
insert into trav select ' 李四 ' , ' 2007-02-01 ' , ' 上海 ' , ' 成都 ' , 3
insert into trav select ' 张三 ' , ' 2007-01-15 ' , ' 广州 ' , ' 上海 ' , 4
insert into trav select ' 张三 ' , ' 2007-02-06 ' , ' 上海 ' , ' 广州 ' , 5
insert into trav select ' 张三 ' , ' 2007-02-18 ' , ' 广州 ' , ' 上海 ' , 6
go
select a.name,a.date,a.comefrom,a.destin,b.date,b.comefrom,b.destin
from trav a inner join trav b on a.name = b.name and a.comefrom = b.destin and a.destin = b.comefrom where a.id < b.id
and not exists ( select 1 from trav where comefrom = b.comefrom and date < b.date and date > a.date)
go
drop table trav
/*
name date comefrom destin date comefrom destin
---------- ----------------------- ---------- ---------- ----------------------- ---------- ----------
张三 2007-01-01 00:00:00.000 上海 广州 2007-01-15 00:00:00.000 广州 上海
张三 2007-02-06 00:00:00.000 上海 广州 2007-02-18 00:00:00.000 广州 上海

(2 行受影响)
*/
-----------------------------------------------------------------------------------------------
 
      
      
       
       SQL code 
      
      
      
      
        
        

-- 日期转换参数,值得收藏
select CONVERT ( varchar , getdate (), 120 )
2004 - 09 - 12 11 : 06 : 08

select replace ( replace ( replace ( CONVERT ( varchar , getdate (), 120 ), ' - ' , '' ), ' ' , '' ), ' : ' , '' )
20040912110608

select CONVERT ( varchar ( 12 ) , getdate (), 111 )
2004 / 09 / 12

select CONVERT ( varchar ( 12 ) , getdate (), 112 )
20040912

select CONVERT ( varchar ( 12 ) , getdate (), 102 )
2004.09 . 12

其它我不常用的日期格式转换方法:

select CONVERT ( varchar ( 12 ) , getdate (), 101 )
09 / 12 / 2004

select CONVERT ( varchar ( 12 ) , getdate (), 103 )
12 / 09 / 2004

select CONVERT ( varchar ( 12 ) , getdate (), 104 )
12.09 . 2004

select CONVERT ( varchar ( 12 ) , getdate (), 105 )
12 - 09 - 2004

select CONVERT ( varchar ( 12 ) , getdate (), 106 )
12 09 2004

select CONVERT ( varchar ( 12 ) , getdate (), 107 )
09 12 , 2004

select CONVERT ( varchar ( 12 ) , getdate (), 108 )
11 : 06 : 08

select CONVERT ( varchar ( 12 ) , getdate (), 109 )
09 12 2004 1

select CONVERT ( varchar ( 12 ) , getdate (), 110 )
09 - 12 - 2004

select CONVERT ( varchar ( 12 ) , getdate (), 113 )
12 09 2004 1

select CONVERT ( varchar ( 12 ) , getdate (), 114 )
11 : 06 : 08.177

-----------------------------------------------------------------------------------------------
 
      
      
       
       SQL code 
      
      
      
      
        
        

-- 我来一段

-- SQL2005

CREATE TABLE #t (id int IDENTITY ( 1 , 1 ) PRIMARY KEY ,nums int )
GO

INSERT INTO #t
SELECT abs (CHECKSUM( NEWID ()) % 100000 )
GO 10000 -- --生成10000笔资料,可以是任意一数字

SELECT * FROM #t
GO
DROP TABLE #t
GO

       
       
---------------------------------------------------------------------------------------------
 
 
固定列数的行列转换

student subject grade
--------- ---------- --------
student1 语文 80
student1 数学 70
student1 英语 60
student2 语文 90
student2 数学 80
student2 英语 100
……
转换为
语文 数学 英语
student1 80 70 60
student2 90 80 100
……
语句如下:select student,
sum(decode(subject,'语文', grade,null)) "语文",
sum(decode(subject,'数学', grade,null)) "数学",
sum(decode(subject,'英语', grade,null)) "英语"
from table
group by student;


--------------------------------------------------------------------------------------------
 
SELECT * FROM TABLENAME
绝对经典,最常用的查询
 
  
  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值