SQL 數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程的參數(shù)問(wèn)題

字號(hào):


    1、SQL 數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程的參數(shù)問(wèn)題
    怎么將SQL數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程中的參數(shù)既作為輸出變量又作為輸出變量?
    [sql] view plaincopy --drop proc proc_test
    --go
    create proc dbo.proc_test
    @in int,
    @out int out,
    @in_out int output
    as
    select @out = @in + @in_out, --1 + 2 = 3
    @in_out = @out + 1 --3 + 1 = 4
    go
    declare @in_p int
    declare @out_p int
    declare @in_out_p int
    set @in_p = 1;
    set @in_out_p = 2
    exec dbo.proc_test @in_p,
    @out_p out,
    @in_out_p output
    select @in_p, --輸入?yún)?shù)
    @out_p, --輸出參數(shù)
    @in_out_p --輸入,輸出參數(shù)
    /*
    (無(wú)列名) (無(wú)列名) (無(wú)列名)
    1 3 4
    */
    2、在存儲(chǔ)過(guò)程中的參數(shù)問(wèn)題。
    下面是問(wèn)題:
    [sql] view plaincopy create table #tableTest(id int identity , name varchar(20),age int,)
    go
    insert into #tableTest
    select '小明',23 union all
    select '小紅',28 union all
    select '小軍',27
    go
    select *from #tableTest
    go
    create proc procTest
    @name varchar(20),
    @age int,
    @IDs varchar(30)
    as
    begin
    select *from #tableTest where 1=1
    end
    --當(dāng)我傳入@name參數(shù)等于 小明,23歲,還有ID在(1,3)的時(shí)候
    --我怎么可以弄成可選的參數(shù)
    --比如,name不為空時(shí)候
    select *from #tableTest where 1=1 and name like '小明'
    --如果name參數(shù)為空的時(shí)候,IDs參數(shù)不為空的時(shí)候
    select *from #tableTest where 1=1 and id in(1,3)
    --請(qǐng)問(wèn)一下,就有參數(shù)不為空的時(shí)候存儲(chǔ)過(guò)程中的SQL追加條件,為空的時(shí)候就不追加,這樣帶可選參數(shù)的存儲(chǔ)過(guò)程怎么寫(xiě),以及怎么調(diào)用,請(qǐng)幫小弟寫(xiě)一個(gè)實(shí)例
    這種問(wèn)題,本質(zhì)上就是根據(jù)傳入的參數(shù)不同,進(jìn)行不同的查詢,也就是where 后面的查詢條件是動(dòng)態(tài)的。
    一般有2中處理方式,一種就是寫(xiě)動(dòng)態(tài)語(yǔ)句,但動(dòng)態(tài)語(yǔ)句由于是動(dòng)態(tài)拼接字符串,所以比較難維護(hù),而且如果存儲(chǔ)過(guò)程需要執(zhí)行多次,那么每次都需要重新編譯,但每次生成的執(zhí)行計(jì)劃,應(yīng)該是比較優(yōu)化的。但如果拼接字符串部分,只是少量的話,還是可以用動(dòng)態(tài)語(yǔ)句的,下面我的解法就是用動(dòng)態(tài)語(yǔ)句來(lái)實(shí)現(xiàn)的,結(jié)構(gòu)清晰,易于維護(hù)。
    另一種,就是通過(guò)在where語(yǔ)句后面寫(xiě)case when來(lái)進(jìn)行判斷,這種方法的好處是不用動(dòng)態(tài)拼接語(yǔ)句,但不易于理解,也不易于修改,因?yàn)閯e人不一定能理解你這么寫(xiě)的意思。另一個(gè)問(wèn)題就是性能的問(wèn)題,因?yàn)樵谠瓉?lái)的公司就用過(guò)這種方法,一段時(shí)間后,查詢非常慢,本來(lái)幾秒就能出結(jié)果,后來(lái)幾分鐘都出不了結(jié)果。說(shuō)實(shí)在的,這種方法要求較高的技巧性,也容易出錯(cuò),不建議使用。
    下面是我的解法,用了動(dòng)態(tài)語(yǔ)句來(lái)實(shí)現(xiàn),但考慮了維護(hù)、測(cè)試方面的要求:
    [sql] view plaincopy --drop table #tableTest
    create table #tableTest(id int identity , name varchar(20),age int,)
    go
    insert into #tableTest
    select '小明',23 union all
    select '小紅',28 union all
    select '小軍',27
    go
    select *from #tableTest
    go
    create proc procTest
    @name varchar(20)=null,@age int = null,@IDs varchar(30) = null
    as
    declare @sql nvarchar(max);
    set @sql = '';
    set @sql = 'select * from #tableTest where 1 = 1';
    set @sql = @sql +
    case when @name is not null
    then ' and name like ' + QUOTENAME(@name +'%','''')
    when @age is not null
    then ' and age = ' + cast(@age AS varchar)
    when @ids Is not null
    then ' and id in (' + @ids +')'
    else ' '
    end
    --打印出語(yǔ)句
    select @sql as '語(yǔ)句'
    --執(zhí)行語(yǔ)句
    --exec(@sql)
    go
    exec procTest
    /*
    語(yǔ)句
    select * from #tableTest where 1 = 1
    */
    exec procTest '小明',23
    /*
    語(yǔ)句
    select * from #tableTest where 1 = 1 and name like '小明%'
    */
    exec procTest @ids = '2,3'
    /*
    語(yǔ)句
    select * from #tableTest where 1 = 1 and id in (2,3)
    */
    備注:如遇到需多個(gè)and參數(shù)連接查詢,SQL語(yǔ)句可寫(xiě)如下
    SET @sql= @sql +
    CASE WHEN @SellerNick <> ''
    THEN ' and SellerNick = '
    ELSE ' '
    END
    SET @sql= @sql +
    CASE WHEN @LogisticsId <> ''
    THEN ' and LogisticsId =
    ELSE ' '
    END
    alter table mytable drop index mdl_tag_use_ix;//mdl_tag_use_ix是上表查出的索引名,key_name