日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

那些可以在數(shù)據(jù)庫里做的事:分頁與過濾

 昵稱10504424 2014-04-10

其實很多非業(yè)務(wù)邏輯的功能,比如分頁,數(shù)據(jù)過濾,可以在程序上面節(jié)省很多內(nèi)存和CPU時間,但往往又找不到一個比較通用有效的方法,花了點時間,終于把我想要的在數(shù)據(jù)庫中分頁和過濾的功能寫了出來,在這里分享。

第一期望:我希望輸入頁碼(pageIndex),每頁顯示的記錄數(shù)(pageSize),然后這個存儲過程就可以給我一個當(dāng)前頁的數(shù)據(jù)集。

首先,我假設(shè)有個表叫Configuration,里面就3個字段,Id, Key, Value,就是一個簡單的數(shù)據(jù)表,定義如下:

再者,一個良好的代碼書寫規(guī)范是非常必要的,該注釋的地方千萬別省,在多數(shù)情況下,代碼的可讀性是非常重要的,除非因性能因素做必須得讓步。

這里用的ROW_NUMBER()來實現(xiàn)分頁,性能必拼SQL的方法好,WITH...AS可以省下一個表變量。最后計算總記錄數(shù)和頁數(shù)很簡單,算下就好了。

第二期望:這樣的,似乎差不多了,但是我還希望能夠有一套規(guī)則,來過濾結(jié)果集,并且還要有類似AND和OR的運算功能,而且我仍舊不希望用inline-script去實現(xiàn),能不用盡量不要用。

為了實現(xiàn)這個期望,我需要先定義怎么傳入過濾規(guī)則,我最終決定用的是xml數(shù)據(jù)類型而不是普通字符串,因為普通字符串有長度限制(如果你說可以用text,那我只能說太奢侈,小弟用不起),定短了可能被截斷出現(xiàn)錯誤輸出,定長了,最多也就8000個字符,也浪費,我不喜歡不確定因素,然而xml不一樣,既是結(jié)構(gòu)化數(shù)據(jù),又有索引支持,可長可短,客戶端也可直接序列化成字符串傳入,非常方便。于是剩下的是,約定一個規(guī)則,確定過濾規(guī)則的數(shù)據(jù)結(jié)構(gòu),在這里我專門寫了一個function來將xml轉(zhuǎn)換成table已被后用。P.S. 如果想傳一個數(shù)組到存儲過程,也可以用xml類型,比字符串加分隔符更安全。

復(fù)制代碼
/*
PROCEDURE:    [dbo].[sp_r_fp_configuration]
OPERATION:    READ
FEATURES:        Paginate, Filter
PURPOSE:        provide a paginated & filterable list from the configuration table
CREATOR:        Jerry Weng
CREATETIME:    2014-4-9
UPDATETIME:    2014-4-9
VERSION:        1.0
*/

CREATE PROCEDURE [dbo].[sp_r_fp_configuration]
    @pageIndex    int = 1,                /*which page of the total page*/
    @pageSize        int=10,                /*how many records show in one page*/
    @filter            xml,                    /*filter string for the records*/
    @recordCount int OUTPUT,        /*output: return the count of the total records in all pages*/
    @pageCount    int OUTPUT            /*output: return the count of the total pages*/
AS
    if(@filter is null)
    begin
        exec dbo.sp_r_p_configuration 
                @pageIndex,
                @pageSize,
                @pageCount=@pageCount OUTPUT, 
                @recordCount=@recordCount OUTPUT
    end
    else
    begin
        
        declare @tmptbl table (row_id int, Id int, [Key] varchar(100), [Value] varchar(200))
    
        declare @startRow int;                -- the row number of the first record in the page
        declare @endRow int;                -- the row number of the last record in the page
        set @startRow = (@pageIndex - 1) * @pageSize + 1;
        set @endRow= @startRow + @pageSize - 1;

        insert into @tmptbl
            select (ROW_NUMBER() over (order by m.Id)) as row_id, m.[Id], m.[Key], m.[Value] 
            from dbo.Configuration as m
            outer apply fun_xmlfilter_parse(@filter,'key') as k
            outer apply fun_xmlfilter_parse(@filter,'value') as v
            where 
            (
                not (isnull(k.[Required],0)=0 and isnull(v.[Required],0)=0) and
                (isnull(k.[Required],0)=0 or (k.[Required] = 1 and isnull(m.[Key],'') = isnull(k.[Match],''))) and
                (isnull(v.[Required],0)=0 or (v.[Required] = 1 and isnull(m.[Value],'') = isnull(v.[Match],'')))
            ) or
            k.[Required] = 0 and isnull(m.[Key],'') = isnull(k.[Match],'') or
            v.[Required] = 0 and isnull(m.[Value],'') = isnull(v.[Match],'')
        
        select [Id], [Key], [Value] from @tmptbl
        where row_id between @startRow and @endRow
    
        -- calculate the record count in all pages
        select @recordCount=COUNT(*) from @tmptbl
        -- calculate the page count
        set @pageCount = CEILING(@recordCount/CAST(@pageSize as float))
    end
RETURN 0
復(fù)制代碼

這里用了一個表變量,注意表變量是可被緩存的,臨時表沒有哦,用表變量不用with...as是因為后面在計算過濾后的總記錄數(shù)的時候,還需用一次過濾后的集合。這里我希望列Key和列Value都可以被過濾,于是用了兩個outer apply來將剛才那個函數(shù)的輸出表附加到每行上,在where比較的地方,先比較Required是1的必要條件,當(dāng)然如果針對某個column沒有rule的話,也就是required is null的情況,是需要排除的,最后再附加連個required=0的可選條件,這樣的話,一個select就可以把各種條件過濾出來了。不過,有個問題是,如果需要過濾的列比較多,那比較語句也要一條條加上去。

最后,來測試下:

我給表填充了這么些數(shù)據(jù):

測試腳本:

輸出,如果需要找null值的話,直接把match屬性去掉就可以了<rule column="value" required="1"/>:

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多