用視圖+存儲過程解決復雜查詢的排序分頁問題


數據庫中復雜的聯查+篩選條件+排序+分頁一直是比較頭疼的問題

 

為了模擬這個問題,首先建立兩個表

create table t_userType (
    id int identity(1,1) not null primary key,
    name varchar(50)
)
GO

create table t_user (
    id int identity(1,1) not null primary key,
    t_userTypeId int not null,
    name varchar(50),
    foreign key (t_userTypeId) references t_userType(id)
)
GO

 

下面插入一些測試數據

  

 

在t_user這個表中,t_userTypeId字段關聯到了t_userType這個表

我們希望在查詢用戶時,同時查詢到這個用戶類型的name,可以通過聯查實現

select u.*, t.name as typeName
    from t_user u
    inner join t_userType t
    on t.id = u.t_userTypeId

 

如果聯查的表多了,就會比較復雜,所以建立一個視圖

create view view_user_andType
as
    select u.*, t.name as typeName
    from t_user u
    inner join t_userType t
    on t.id = u.t_userTypeId
go

 

這時,使用下面的語句,就能得到我們想要的結果

select * from view_user_andType

 

如果想提供分頁功能的話,需要這樣寫

select top 5 * from view_user_andType where id not in (select id top 0 view_user_andType)

 

加入條件過濾和排序

select top 5 * from view_user_andType 
where id>1 and 
    id not in (
        select top 0 id view_user_andType 
        where id>1 order by id) 
order by id

 

如果每個表的聯查都寫成這樣,也是比較頭大的

所以通過一個存儲過程,封裝分頁和排序邏輯

-- 存儲過程:通用分頁
--
-- 分頁查詢某個表或視圖
--
-- 參數列表:
--        srcTableName:視圖或表名
--        idColumnName:主鍵列名
--        pageSize:每頁長度(1~n)
--        pageIndex:頁碼(1~n)
--        condition:過濾條件
--        orderBy:排序方式,必須為查詢結果中的字段名
--        isDesc:是否倒序,可選值(true, false)
--
SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO
IF OBJECT_ID ( 'proc_selectByPage', 'P' ) IS NOT NULL 
    Drop PROCEDURE [proc_selectByPage];
GO
create  procedure [dbo].[proc_selectByPage]
    @srcTableName varchar(50),
    @idColumnName varchar(50) = 'id',
    @pageSize int = 10,
    @pageIndex int = 1,
    @condition varchar(500) = '',
    @orderBy varchar(50),
    @isDesc varchar(50) = 'false'
AS
begin

    -- 參數容錯
    if (@pageIndex <= 0)
    begin
        set @pageIndex = 1
    end

    -- 組裝語句
    declare @sql1 varchar(4000)
    set @sql1 = 'select top ' + cast (@pageSize as varchar(50)) + 
                ' * from ' + @srcTableName +
                ' where (' + @idColumnName +
                        ' not in (select top ' + cast ((@pageSize * (@pageIndex-1)) as varchar(50)) +
                        ' ' + @idColumnName +
                        ' from ' + @srcTableName
    
    if ( @condition <> '' )
    begin
        set @sql1 = @sql1 + ' where ' + @condition
    end
                        
    set @sql1 = @sql1 + ' order by ' + @orderBy
                        
    if ( @isDesc = 'true' ) 
    begin 
        set @sql1 = @sql1 + ' desc ';
    end
    else if ( @isDesc = 'false' )
    begin
        set @sql1 = @sql1 + ' asc ';
    end

    set @sql1 = @sql1 + '  ) '
    
    if ( @condition <> '' )
    begin
        set @sql1 = @sql1 + ' and ' + @condition
    end
    
    set @sql1 = @sql1 + ')'
    
    set @sql1 = @sql1 + ' order by ' + @orderBy
    
    if ( @isDesc = 'true' ) 
    begin 
        set @sql1 = @sql1 + ' desc ';
    end
    else if ( @isDesc = 'false' )
    begin
        set @sql1 = @sql1 + ' asc ';
    end
    
    -- 輸出語句,並執行
    print @sql1
    exec(@sql1)

end
GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

 

再實現相同的功能就可以這樣寫

exec proc_selectByPage 'view_user_andType', 'id', 3, 2, '', 'name', 'false'

 

可以兼容表或視圖的分頁,sqlserver2000下測試通過

 


免責聲明!

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



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