SQL Server進階(十一)存儲過程


變量

局部變量  

1.聲明局部變量

@where NVARCHAR(4000),
@whereFORhruserinfo NVARCHAR(4000) = '',
@order NVARCHAR(200) = '',
@pagesize INT,--每頁有幾條數據
@page INT,--當前頁數
@totalRecorder INT OUTPUT
View Code

2.為變量賦值

SET @變量名 =--set用於普通的賦值
SELECT @變量名 =--用於從表中查詢數據並賦值,,可以一次給多個變量賦值

SET @name=‘張三’
SET @id = 1
SELECT @name = sName FROM student WHERE sId=@id
View Code

3.輸出變量的值

SELECT 以表格的方式輸出,可以同時輸出多個變量;而PRINT 則是以文本的方式輸出,一次只能輸出一個變量的值

SELECT @name,@id
PRINT @name
PRINT @id
print @name,@id  --錯誤!!
View Code

全局變量

 

用全局變量

select @@LANGUAGE as '當前使用語言'
select @@SERVERNAME as '當前服務器名稱'
select @@TRANCOUNT as '當前連接打開的事務數'
select @@MAX_CONNECTIONS as '可以同時連接的最大數目'
select @@VERSION as '當前服務器版本'
select @@ERROR as '最后一個T-SQL錯誤的錯誤號'
View Code

IF ELSE

條件選擇語法

IF(條件表達式)
  BEGIN --相當於C#里的{
    語句1  ……
  END --相當於C#里的}
ELSE
 BEGIN
    語句1
    ……
  END
View Code

WHILE

循環語句語法

WHILE(條件表達式)
  BEGIN --相當於C#里的{
    語句
    ……
    continue --退出本次循環
    BREAK    --退出整個循環
  END --相當於C#里的}
View Code

計算1-100之間所有奇數的和

declare @index int = 1
declare @sum int = 0
while(@index <= 100)
begin
    if(@index%2!=0)
    begin
        set @sum=@sum+@index
    end
    set @index=@index+1
end
View Code

存儲過程

新建存儲過程

Create PROCEDURE [dbo].[p_test]
    @type int
AS
BEGIN
    declare @count int
    declare @result varchar(50)
    if(@type =1)
        begin
            select  @count = (select count(*) from dbo.UserGrowthDetail)
            set @result='求第一個總數'
            print @result
            return @count
        end
    else if(@type =2)
        begin
            select  @count = (select count(*) from dbo.UserGrowthValue)
            set @result='求第二個總數'
            print @result
            return @count
        end
END
View Code

執行存儲過程

GO

DECLARE    @return_value int

EXEC    @return_value = [dbo].[p_test]
        @type = 1

SELECT    'Return Value' = @return_value

GO
View Code

 存儲過程通用分頁

Create  PROCEDURE [dbo].[WF_Pager]
@tblName varchar(255), -- 表名
@strGetFields varchar(1000), -- 返回字段列表要足夠大
@orderName varchar(255), -- 字段名用於排序
@OrderType bit = 0,--0 升序 1降序
@PageSize int = 10, -- 頁尺寸
@PageIndex int, -- 頁碼
@strWhere varchar(1000) = '' ,-- 查詢條件(注意:不要加where) 
@RecordCount int output --總數
AS
BEGIN
    DECLARE @sql nvarchar(4000)
    declare @sortStr varchar(50)--排序方式
    if @OrderType!=1  --升序
    set @sortStr=' asc '
    else      --降序
    set @sortStr=' desc '
    if @strWhere !=''
    set @strWhere=' where '+@strWhere
    SELECT @sql =N'
    DECLARE @temp int;
    DECLARE @minRecord int;
    DECLARE @PageSize int;
    DECLARE @PageIndex int;    
    SET @temp = 0
    SET @minRecord = 0
    SET @PageSize ='+ cast(@PageSize as varchar(10)) +'
    SET @PageIndex = '+ cast(@PageIndex as varchar(10)) +'
    SELECT @RecordCount = COUNT(0) FROM '+@tblName+ @strWhere +'
    --    限制每頁記錄數,默認每頁10項記錄    --
    IF(@PageSize < 1)
        SET @PageSize = 10
    --    限制頁號 BEGIN    --
    IF(@PageIndex < 1)
        SET @PageIndex = 1
    DECLARE @MaxPageIndex INT  --    最大頁數。
    SET @MaxPageIndex = @RecordCount / @PageSize --(完整數量的頁的數量)
    IF(@RecordCount % @PageSize > 0)
    BEGIN
        SET @MaxPageIndex = @MaxPageIndex + 1        
    END
    IF (@MaxPageIndex = 0)
    BEGIN
        SET @MaxPageIndex=1
    END
    IF(@PageIndex > @MaxPageIndex)
        SET @PageIndex = @MaxPageIndex
    SET @minRecord = (@PageIndex - 1) * @PageSize;
    SET @temp = @PageIndex * @PageSize;    
SELECT * FROM
    (
        SELECT 
        ROW_NUMBER() OVER (ORDER BY '+@orderName+@sortStr+') AS Item,'+@strGetFields+'  
        FROM '+@tblName+ @strWhere +'
        ) AS T
    WHERE T.Item >= @minRecord + 1
    AND T.Item <= @temp '
    --執行
    EXEC SP_EXECUTESQL @sql, N'@RecordCount varchar(10) output',@RecordCount output
    SELECT @RecordCount
END
View Code

存儲過程綜合示例

USE [SCST]
GO
/****** Object:  StoredProcedure [dbo].[p_test]    Script Date: 2018/8/23 19:43:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[p_test]
    @strWhere varchar(1000),
    @PageSize int = 10, -- 頁尺寸
    @PageIndex int = 0, -- 頁碼
    @RecordCount int output --輸出參數 總數
AS
BEGIN
    DECLARE @Result nvarchar(50)
    IF(@strWhere=1)
        BEGIN
            --CET公共表表達式
            with tbStudent as
            (
                select * from Student where Ssex = ''
            )
            SELECT @Result = (select count(*) from tbStudent)

            --輸出參數賦值
            SELECT @RecordCount=1
        END
    ELSE
        BEGIN

            SELECT dense_rank() OVER (ORDER BY s.Sage DESC) AS Rank,ROW_NUMBER() OVER(ORDER BY s.S# ASC) as RowNumber,s.S#,s.Sname,s.Ssex,ISNULL(s.Ssex,'空值') as Ssex,
            Sage=(case  Sage
                        when 17 then ''
                        when 18 then '正好'
                        when 19 then ''
                  end
                  )    
            from Student s

            SELECT CAST('12' AS int)

            SELECT CONVERT(VARCHAR(19),GETDATE())

            --exists

            --while
            declare @index int = 1
            declare @sum int = 0
            while(@index <= 100)
            begin
                if(@index%2!=0)
                begin
                    set @sum=@sum+@index
                end
                set @index=@index+1
            end
            print @sum


            SET @Result = '2'
            SELECT @RecordCount=2
        END
        print @Result
    return  @Result
END
View Code

 

USE [Points2019]
GO

/****** Object:  StoredProcedure [dbo].[p_Page]    Script Date: 2019/8/6 13:28:52 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[p_Page]
  -- Add the parameters for the stored procedure here
    @SQL           NVARCHAR(4000),
    @Order         NVARCHAR(200),
    @CurPage       INT,
    @PageRows      INT,
    @TotalRecorder INT OUTPUT
AS
  BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    SET NOCOUNT ON;
    DECLARE @ExceSQL NVARCHAR(4000)

    --獲得記錄數
    SET @ExceSQL = 'select @TotalRecorder=count(*) from ' +
                   substring(@SQL, charindex('YanFaFrom', @SQL) + 9, len(@SQL) - charindex('YanFaFrom', @SQL) - 8)

    EXECUTE sp_executesql @ExceSQL, N'@TotalRecorder int output', @TotalRecorder OUTPUT

    --設置開始行號
    DECLARE @start_row_num AS INT
    SET @start_row_num = (@CurPage - 1) * @PageRows + 1

    --設置標識語句
    DECLARE @RowNumber NVARCHAR(300)
    IF (isnull(@Order, '') = '')
      BEGIN
        SET @Order = '(select 0)'
      END
    SET @RowNumber = ', ROW_NUMBER() OVER(ORDER BY ' + @Order + ') as RowNumber from '

    SET @SQL = Replace(@SQL, 'YanFaFrom', @RowNumber)

    --設置查詢語句
    SET @ExceSQL = 'WITH tmp AS (' + @SQL + ')
        select * from tmp where RowNumber between ' + Convert(NVARCHAR, @start_row_num)
                   + ' And ' + Convert(NVARCHAR, @start_row_num + @PageRows - 1) + ' ORDER BY RowNumber asc'

    EXECUTE (@ExceSQL)
    PRINT @ExceSQL
  END

GO
[dbo].[p_Page]

存儲過程和函數的區別

存儲過程是第一次編譯之后就會被存儲的下來的預編譯對象,之后無論何時調用它都會去執行已經編譯好的代碼。
而函數每次執行都需要編譯一次。總結下來有下面幾個區別:

基本不同:

  函數必須有一個返回值而存儲過程則不是必須的(存儲過程可以返回0個到n個值);

  函數只能有輸入參數而存儲過程可以同時又輸入和輸出參數;

  函數至少有一個參數而存儲過程可能需要n個參數;

  函數可以被存儲過程調用而存儲過程不可以被函數調用;

高級不同:

  存儲過程允許SELECT還有DML(INSERT/UPDATE/DELETE)語句而函數只能使用SELECT語句;

  存儲過程不可以使用在WHERE/HAVING/SELECT語句中而函數可以;

  返回表變量的函數可以和其他表進行JOIN操作;

  內聯函數可以看做一個帶參數的VIEW去和其他表進行JOIN操作;

  存儲過程可以使用try-catch塊進行異常處理二函數不可以;

  存儲過程中可以使用事務而函數不可以;

總結:

  函數有且只有一個輸入參數和一個返回值,而存儲過程沒有這個限制;

  返回表變量的函數可以當做VIEW或者臨時表用在WHERE/HAVING/SELECT/JOIN語句中而存儲過程不可以;

  存儲過程中可以使用try-catch塊和事務,而函數中不可以

實戰

 1.可以將耗時的查詢先查出來放到臨時表中,給需要創建索引的字段創建索引。然后用該臨時表和主表做join查詢。

 SET @s = 'select * into # from v_hruserinfo WHERE 1=1 ' + @whereFORhruserinfo+';'

 

select * into #Table  from v_Table
CREATE UNIQUE INDEX TMPUNIQUEHRU ON #Table(XXField) 
CREATE  INDEX TMPHRU ON #Table (XXField) 

2.使用公用表表達式可以使存儲過程更加優雅

WITH CTE AS 
( 
)

 

資料

https://www.cnblogs.com/skybreak/p/3642593.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM