MSSQL相关应用收集

在查找问题的时候,无意搜索到这个Blog:http://blogs.x2line.com,发现有好一些内容不错,实际项目完全有可能用到,特收集起来

 1、SQL Tip: HowTo Convert Delimited String to Table

Many times we need to deal with lists in T-SQL, for instance we need to have a list of values to pass it to IN clause in SQL. This list is supposed to look like delimited string. However we can not pass it to T-SQL procedure as a string because T-SQL compiler can not interpret delimited string as a list of values.

For MSSQL - the list of values is of table type, so we need to have a tool to convert delimited string to table. The function below does just that. So we are able to pass delimited strings to the procedure, convert this string to table and use it later in SQL IN close or in joins.

 

ContractedBlock.gif ExpandedBlockStart.gif Code
create function F_TBL_VALS_FROM_STRING
(
@p_str varchar(1000))
returns @tbl table (VAL int)
as
begin
    
set @p_str = @p_str + ','
    
declare @p_counter int
    
declare @p_len int
    
declare @p_curr_char varchar(1)
    
declare @p_char varchar(6)
    
declare @p_num int
    
set @p_len = len(@p_str
    
set @p_counter = 1
    
set @p_curr_char = ''
    
set @p_char = ''

    
-- loop
    while @p_counter <= @p_len 
    
begin
        
set @p_curr_char = substring(@p_str@p_counter1)
        
if (@p_curr_char <> ',')
        
begin
            
set @p_char = @p_char + @p_curr_char         
        
end
        
else
        
begin  
            
set @p_num = convert(int@p_char)         
            
insert into @tbl values(@p_num)
            
set @p_char = ''
        
end
       
set @p_counter = @p_counter + 1
    
end
    
return
end

 

2、MSSQL: Recompile Stored Procedures, Views, Functions

Sometimes after massive MSSQL schema update to online scalable production environment there is a need to recompile all stored procedures, user-defined functions and views in the database in order to MSSQL will refresh stores procedures execution plans stored in memory in order to reflect recent schema changes. Below is a small MSSQL code snipped written solely for maintenance purposes. It goes through database objects and performs recompilation using sp_recompile system stored procedure.

ContractedBlock.gif ExpandedBlockStart.gif Code
/*

    Recompile Procs, Views, UDF
    In The Database

*/

DECLARE proccurs CURSOR
FOR
    
SELECT [name]
      
FROM sysobjects
     
WHERE xtype in ('p''v''fn')

OPEN proccurs
DECLARE @pname VARCHAR(60)

FETCH NEXT FROM proccurs INTO @pname
WHILE @@fetch_status = 0
BEGIN

    
EXEC sp_recompile @pname

    
FETCH NEXT FROM proccurs INTO @pname
END
CLOSE proccurs
DEALLOCATE proccurs


 This MSSQL code snipped can easily be implemented as a stored procedure.

 

3、T-SQL: Output Parameter in sp_executesql

 sp_executesql is MSSQL system procedure used to execute dynamic SQL (SQL string built dynamically). Sometimes there is a need to return output parameter from that dynamic SQL. Below is a small T-SQL code snippet that demonstrates how to do it.

 

ContractedBlock.gif ExpandedBlockStart.gif Code
DECLARE @i INT
EXEC sp_executesql N'SELECT @i = 1', N'@i INT OUTPUT'@i OUTPUT
SELECT @i

 

 

 4、MSSQL Tip: Rebuild Clustered Indexes

 Rebuild clustered index in the database tables. This code uses cursor to run through user tables. Also it uses dbcc dbreindex command to rebuild index. Use this with care since each rebuild hangs table up.

 

ContractedBlock.gif ExpandedBlockStart.gif Code
declare tabcurs cursor
for
   
select name
   
from sysobjects
   
where xtype = 'u'
open tabcurs
declare @tname varchar(30)
fetch next from tabcurs into @tname
while @@fetch_status = 0
begin
   
dbcc dbreindex(@tname)
   
fetch next from tabcurs into @tname
end
close tabcurs
deallocate tabcurs

 

 5、MSSQL Tip: Get Table Primary Key Column(s)

 Suppose the following MSSQL server problem. We know table name and need to get its Primary Key columns programmatically. In order to do it we will use the following system tables:

sysobjects - for all user objects.
sysindexkeys - for indexes and keys.
syscolumns - for tables columns.

The query will look like so:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT [name]
  
FROM syscolumns 
 
WHERE [id] IN (SELECT [id] 
                  
FROM sysobjects 
                 
WHERE [name] = @table_name)
   
AND colid IN (SELECT SIK.colid 
                   
FROM sysindexkeys SIK 
                   
JOIN sysobjects SO ON SIK.[id] = SO.[id]  
                  
WHERE SIK.indid = 1
                    
AND SO.[name] = @table_name)

sysindexkeys.indid equals to 1 for clustered indexes.

 

6、T-SQL Query: Select Middle Record

 SELECT TOP 1 query in T-SQL helps to find the first or the last record of the table data sorted by some criteria. But what if we need to find exactly middle record entry in the table ? Below is a small T-SQL query snippet that demonstrates a technique how to get middle record in a single query (pay attention to the inline view used):

 

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT TOP 1 UserId
  
FROM (SELECT TOP 50 PERCENT UserId 
          
FROM T_USERS WITH (NOLOCK)
         
ORDER BY UserId ASCAS T1 
 
ORDER BY 1 DESC

 

7、MSSQL Tip: Get Primary Table in Relationship

How to get Primary Table, having the name of Foreign table in relation ? We can use the following MSSQL system tables:

sysobjects - for all user objects.
sysforeignkeys - for foreign keys.
syscolumns - for tables columns.

Build the following query:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT SOP.[name] 
  
FROM sysforeignkeys SFK 
  
JOIN sysobjects SOF ON (SFK.fkeyid = SOF.[id]
  
JOIN sysobjects SOP ON (SFK.rkeyid = SOP.[id]
  
JOIN syscolumns C ON (C.[id] = SOF.[id] AND C.colid = SFK.fkey)  
 
WHERE SOF.[name] = @foreign_table_name 
   
AND C.[name] = @foreign_col_name 

Pay attention how sysobjects is used twice in a query.


8、ROWNUM [ PL/SQL ] Analog for T-SQL

 There is no ROWNUM Analog in T-SQL. ROWNUM is used in PL/SQL to to get the number of rows the query returns in the same query. There is no easy way to perform the same trick in T-SQL query. Small snippet below demonstrates the easy way to achieve the same goal using inner view.

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT (SELECT SUM(1
          
FROM employee t1 
         
WHERE t1.emp_id <= t2.emp_id) AS rownum, t2.* 
  
FROM employee t2

 

 Use in small tables only, since it is not performant on large databases.


9、MSSQL Tip: Get Connected Columns in Related Tables

 How to get Foreign Key related columns, having the names of Primary and Foreign tables ? We can use the following MSSQL system tables:

sysobjects - for all user objects.
sysforeignkeys - for foreign keys.
syscolumns - for tables columns.

Build the following query:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT [name] 
  
FROM syscolumns 
 
WHERE [id] IN (SELECT [id] 
                  
FROM sysobjects 
                 
WHERE [name] = @foreign_table_name
   
AND colid IN (SELECT fkey
                   
FROM sysforeignkeys SFK 
                   
JOIN sysobjects SOF ON SFK.fkeyid = SOF.[id] 
                   
JOIN sysobjects SOP ON SFK.rkeyid = SOP.[id]
                  
WHERE SOF.[name] = @foreign_table_name
                    
AND SOP.[name] = @primary_table_name)

 

10、MSSQL: Change tables owner to dbo with sp_changeobjectowner

 Sometimes there is a need to change all tables in the database to be owned by dbo for maintenance or to fix up accidental errors. All tables owned by dbo schema is usually best practices in the database application development with MSSQL while we can meet different approaches in real life...

The following small SQL code snippet goes through all user tables in the database and changes their owner to dbo. It uses sp_changeobjectowner system stored procedure:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
DECLARE tabcurs CURSOR
FOR
    
SELECT 'SOMEOWNER.' + [name]
      
FROM sysobjects
     
WHERE xtype = 'u'

OPEN tabcurs
DECLARE @tname NVARCHAR(517)
FETCH NEXT FROM tabcurs INTO @tname

WHILE @@fetch_status = 0
BEGIN

    
EXEC sp_changeobjectowner @tname'dbo'

    
FETCH NEXT FROM tabcurs INTO @tname
END
CLOSE tabcurs
DEALLOCATE tabcurs

 

 11、俺自己整理的

 

ContractedBlock.gif ExpandedBlockStart.gif Code
/*
应用:每个类别下的数据,各取3条
注意:此语句是用title来判断大小的,像实例中有2条数据是一样的,所以还存在点问题
*/
DECLARE @daTable TABLE(
title 
nvarchar(100),
category 
int
)

INSERT INTO @daTable
          
SELECT N'ABCDEF'1
UNION ALL SELECT N'XYZ'1
UNION ALL SELECT N'WXYS'1
UNION ALL SELECT N'KDSADA'1
UNION ALL SELECT N'DLSADJK'1
UNION ALL SELECT N'ANMMAF'1
UNION ALL SELECT N'BBBBBB'1
UNION ALL SELECT N'BBBBBB'1
UNION ALL SELECT N'ZZZZZZZ'1
UNION ALL SELECT N'CCC'2
UNION ALL SELECT N'PWKKKASDF'2
UNION ALL SELECT N'WIOASF'2
UNION ALL SELECT N'IOASFHSFA'2
UNION ALL SELECT N'PPPPPPPPPP'3
UNION ALL SELECT N'QQQQQQQQ'3
UNION ALL SELECT N'OOOOOOOOO'3
UNION ALL SELECT N'HHHH'3
UNION ALL SELECT N'LLLLLL'3
UNION ALL SELECT N'LLsisl'4

SELECT title
     , category
FROM @daTable AS t
WHERE ( SELECT COUNT(*)
        
FROM @daTable
        
WHERE category = t.category
        
AND title < t.title ) < 3
ORDER BY t.category


DECLARE @gencalendar TABLE (cal_date DATETIME PRIMARY KEY)
DECLARE @p_date SMALLDATETIME
DECLARE @date smalldatetime
SET @p_date = '20040101'
SET @date = '20040504'

WHILE @date <= '20041231'
BEGIN
    
INSERT INTO @gencalendar(cal_date)
    
VALUES(@p_date)

    
SET @p_date = dateadd(d, 1@p_date)
END

SELECT * 
  
FROM @gencalendar

 

根据帮助,使用WITH写的一个无限级类别的列表(可以显示层次关系,理论上无限级,实际会有实际情况不同有限制)

 

ContractedBlock.gif ExpandedBlockStart.gif Code
CREATE TABLE [dbo].[tb_WEB_ArticleType] (
    
[At_Id]                     [int] IDENTITY (11Not Null,
    
[At_ActualId]            [int] NOT NULL,
    
[At_ParentId]            [int] NOT NULL CONSTRAINT DF_tb_WEB_ArticleType_ParentId DEFAULT(0),
    
[At_TypeClass]            [int] NOT NULL CONSTRAINT DF_tb_WEB_ArticleType_TypeClass DEFAULT(0),
    
[At_TypeShowName]        [nvarchar](100NOT NULL CONSTRAINT DF_tb_WEB_ArticleType_TypeShowName DEFAULT(N''),
    
[At_TypeName]            [nvarchar](100NOT NULL CONSTRAINT DF_tb_WEB_ArticleType_TypeName DEFAULT(N''),
    
[At_OrderBy]            [int] NOT NULL CONSTRAINT DF_tb_WEB_ArticleType_OrderBy DEFAULT(0),
    
    
CONSTRAINT [PK_tb_WEB_ArticleType] PRIMARY KEY  CLUSTERED 
    (
        
[At_ActualId],
        
[At_TypeShowName]
    )  
ON [PRIMARY] 
ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [IX_tb_WEB_ArticleType_1] ON [dbo].[tb_WEB_ArticleType] ([At_Id])
CREATE NONCLUSTERED INDEX [IX_tb_WEB_ArticleType_2] ON [dbo].[tb_WEB_ArticleType] ([At_ActualId][At_Id])
CREATE NONCLUSTERED INDEX [IX_tb_WEB_ArticleType_3] ON [dbo].[tb_WEB_ArticleType] ([At_CreatedDate] Desc)
CREATE NONCLUSTERED INDEX [IX_tb_WEB_ArticleType_4] ON [dbo].[tb_WEB_ArticleType] ([At_ActualId][At_TypeShowName])
GO

exec sp_addextendedproperty N'MS_Description', N'文章分类表', N'user', N'dbo', N'table', N'tb_WEB_ArticleType'

exec sp_addextendedproperty N'MS_Description', N'自增标识',    N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_Id'
exec sp_addextendedproperty N'MS_Description', N'实名ID',    N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_ActualId'
exec sp_addextendedproperty N'MS_Description', N'上级分类标识',    N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_ParentId'
exec sp_addextendedproperty N'MS_Description', N'分类类型(0为系统类别,1为实名新增的)',    N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_TypeClass'
exec sp_addextendedproperty N'MS_Description', N'显示分类名称', N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_TypeShowName'
exec sp_addextendedproperty N'MS_Description', N'内置分类名称(用于页面标签)', N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_TypeName'
exec sp_addextendedproperty N'MS_Description', N'排序号', N'user', N'dbo', N'table', N'tb_WEB_ArticleType', N'column', N'At_OrderBy'
GO


WITH RecursionArticleType(At_Id, At_ActualId, At_ParentId, At_TypeClass, At_TypeShowName, At_TypeName, At_OrderBy, At_sLevel, At_iLevel, At_Ladder)
AS
(
    
SELECT At_Id, At_ActualId, At_ParentId, At_TypeClass, At_TypeShowName, At_TypeName, At_OrderBy, At_sLevel=CONVERT(nvarchar(1000),''), At_iLevel=1, At_Ladder=CONVERT(nvarchar(3000), At_Id)
    
FROM tb_WEB_ArticleType
    
WHERE
        At_ActualId 
= 173764 AND At_ParentId = 0    
    
UNION ALL SELECT
        R1.At_Id, 
        R1.At_ActualId, 
        R1.At_ParentId,
        R1.At_TypeClass,
        R1.At_TypeShowName, 
        R1.At_TypeName, 
        R1.At_OrderBy, 
        
CONVERT(nvarchar(1000), REPLICATE('*', At_iLevel)),
        At_iLevel 
+ 1,
        At_Ladder 
= CONVERT(nvarchar(3000), RTRIM(At_Ladder)+N'|'+cast(R1.At_Id AS nvarchar(100)))
     
FROM tb_WEB_ArticleType as R1
     
JOIN RecursionArticleType as R2 ON R1.At_ParentId = R2.At_Id
)

SELECT * FROM RecursionArticleType ORDER BY At_Ladder, At_OrderBy, At_Id

 

结果(可以把At_sLevel 的值替换成空格就会呈现层次关系,At_iLevel 为当前是第几级分在):

At_Id       At_ActualId At_ParentId At_TypeClass At_TypeShowName    At_TypeName   At_OrderBy   At_sLevel    At_iLevel   At_Ladder
--------- ----------- ----------- ------------ ----------------  -------------  ----------  -----------  ----------- ------------
4           173764       0           0            分类名称      分类名称                1                           1           4
5           173764       0           1            分类名称1      分类名称1             2                          1           5
11          173764      5           1            xxxxx          xxxxx                 1          *              2           5|11
12          173764      11         1            uuuuu              uuuuu             1          **             3           5|11|12
6           173764       0           1            分类名称xx                             3                            1           6

 

由于MSSQL2000不支持WITH,所以又整了一个递归函数(注:对于这样的无限级分类,递归在效率上是很低的,但却很好使,代码也明了)

 

ContractedBlock.gif ExpandedBlockStart.gif Code
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[fn_ArticleTypeSubIds]'and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[fn_ArticleTypeSubIds]
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

/*
    递归列出指定类别下的子类别,@OperateType为预留参数,用于以后扩展
    Written By Net205
    Date:2009-01-08
*/
CREATE FUNCTION [dbo].[fn_ArticleTypeSubIds] (@PId int@ActualId int@iLevel int@OperateType int)
    
RETURNS @ReturnTable TABLE(
        RtIdent 
INT IDENTITY(1,1NOT NULL,
        RtId 
int,
        RtLevel 
int
    )
AS
BEGIN
    
DECLARE @TempTable TABLE(
        TtIdent 
INT IDENTITY(1,1NOT NULL,
        TtId 
int,
        TtLevel 
int        
    )
    
--取子类别的下所有类别写入表变量
    SET @iLevel = isNull(@iLevel0+ 1
    
INSERT INTO @TempTable(TtId, TtLevel) SELECT At_Id, @iLevel FROM tb_WEB_ArticleType WHERE At_ActualId=@ActualId  AND At_ParentId=@PId ORDER BY At_OrderBy, At_Id
    
    
--循环表变量
    DECLARE @getId int@getLevel int@ident int
    
SELECT TOP 1 @getId = TtId, @getLevel = TtLevel FROM @TempTable ORDER BY TtIdent
    
Set @ident = @@RowCount
    
WHILE @ident=1
    
BEGIN
        
DELETE FROM @TempTable WHERE TtId=@getId
        
INSERT INTO @ReturnTable(RtId, RtLevel) SELECT @getId@getLevel
        
INSERT INTO @ReturnTable(RtId, RtLevel) SELECT RtId, RtLevel FROM dbo.fn_ArticleTypeSubIds(@getId@ActualId@iLevel@OperateTypeORDER BY RtIdent
        
        
SELECT TOP 1 @getId = TtId, @getLevel = TtLevel  FROM @TempTable ORDER BY TtIdent
        
Set @ident = @@RowCount
    
END     

    
RETURN
END

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

 

使用:

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT b.*, a.RtLevel AS At_iLevel, REPLICATE(' ', a.RtLevel) AS At_sLevel 
FROM dbo.fn_ArticleTypeSubIds(0,173764,0,0) a 
    
INNER JOIN tb_WEB_ArticleType b ON a.RtId=b.At_Id
ORDER BY a.RtIdent

转载于:https://www.cnblogs.com/net205/archive/2009/01/13/1374758.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值