天天看點

不固定參數的存儲過程

我們知道存儲過程是不支援不固定參數情況的(包括數組參數),可是有時候我們的參數又必須是不固定的,怎麼辦呢?我想此時不妨使用字元串參數來幫助我們解決這種情況,利用字元串分割的方法将一個參數分割成數個參數來解決。下面我們看一個例子:

假設現在給你一個産品資訊清單(顯示出各個商品的基本資訊),現在我想要根據所選擇商品進行統計(任意選擇幾種),例如統計出價格<10,11-20,21-30,31-40,41-50,50以上的商品個有多少個(姑且認為就統計這些)。此時如果使用存儲過程就勢必需要傳入所選商品的id作為參數,但是id個數是不固定的。此時估計會有人這樣寫:

不固定參數的存儲過程
不固定參數的存儲過程

set ansi_nulls on

go

set quoted_identifier on

-- =============================================

-- author: jianxin160

-- create date: 2010.11.05

-- description: 統計商品

alter procedure statproductinfo

(

@ids varchar(8000)

)

as

begin

declare @followingten int

declare @eleventotwenty int

declare @twentyonetothirty int

declare @thirtyonetofourty int

declare @fourtyonetofifty int

declare @fiftyormore int

select @followingten=count(*)

from dbo.products

where productid in(@ids) and unitprice<10

select @eleventotwenty=count(*)

where productid in(@ids) and unitprice between 11 and 20

select @twentyonetothirty=count(*)

where productid in(@ids) and unitprice between 21 and 30

select @thirtyonetofourty=count(*)

where productid in(@ids) and unitprice between 31 and 40

select @fourtyonetofifty=count(*)

where productid in(@ids) and unitprice between 41 and 50

select @fiftyormore=count(*)

where productid in(@ids) and unitprice>50

select @followingten as '<$10',@eleventotwenty as '$11-$20',

@twentyonetothirty as '$21-$30',@thirtyonetofourty as '$31-$40',

@fourtyonetofifty as '$41-$50',@fiftyormore as '>$50'

end

不固定參數的存儲過程

其實如果你測試一下(例如:exec dbo . statproductinfo '3,4,8,10,22')是有問題的,sql server認為這整個是一個參數,轉換時出錯。此時我們想一下如果這些字段在一個虛表中就容易操作多了,但是一般虛表是有其他表通過查詢得到,現在根本無法查詢又哪來的虛表呢?聰明的朋友或許已經想到可以使用"表值函數"。對,答案就是使用"表值函數"。我們知道"表值函數"可以傳回一個"table"類型的變量(相當于一張虛表,存放于記憶體中),我們首先将字元串分割存放到"表值函數"的一個字段中,然後我們再從"表值函數"中查詢就可以了(這個例子也是"表值函數"的一個典型應用)。具體sql如下:

不固定參數的存儲過程
不固定參數的存儲過程

-- author: cmj

-- description: 傳回一個table,隻有一列,每一行的資料就是分割好的字元串

create function getsplitfieldsbystring

@tosplitstring varchar(1000),

@splitchar varchar(10)

returns

@tb table(sp varchar(100))

declare @i int

set @tosplitstring=rtrim(ltrim(@tosplitstring))

set @i=charindex(@splitchar,@tosplitstring)

while @i>0

insert @tb values(left(@tosplitstring,@i-1))

set @tosplitstring=right(@tosplitstring,len(@tosplitstring)-@i)

if len(@tosplitstring)>0

insert @tb values(@tosplitstring)

return

不固定參數的存儲過程

然後我們稍微修改一下存儲過程:

不固定參數的存儲過程
不固定參數的存儲過程

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice<10

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice between 11 and 20

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice between 21 and 30

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice between 31 and 40

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice between 41 and 50

where productid in(select sp from dbo.getsplitfieldsbystring(@ids,',')) and unitprice>50

select @followingten as '<$10',@eleventotwenty as '$11-$20',@twentyonetothirty as '$21-$30',

@thirtyonetofourty as '$31-$40',@fourtyonetofifty as '$41-$50',@fiftyormore as '>$50'

不固定參數的存儲過程

這樣通過執行exec dbo . statproductinfo '3,4,8,10,22' 就可以得到想要的結果了:

不固定參數的存儲過程
不固定參數的存儲過程
不固定參數的存儲過程