如何将存储过程更改为表值函数?

Posted

技术标签:

【中文标题】如何将存储过程更改为表值函数?【英文标题】:how to change stored procedure into table valued function? 【发布时间】:2014-09-30 04:46:52 【问题描述】:

这是我想要更改为表值函数的存储过程。我不知道如何创建表值函数,请帮助我

ALTER procedure [dbo].[GENRATE_BATCHNO]
    @StrBatchNo varchar(200) output,
    @BatchNum bigint output,
    @RetType bigint output,
    @Fid int,
    @WcID int,
    @PrCompID bigint,
    @BsProductID bigint,
    @CreationDt datetime
as 
begin
    Declare @RestartFrom int, @BatchID bigint,@BatchMaxVal bigint,@ParaType int, @BatchValue varchar(50),@BatchFormat varchar(10),
    @Digits bigint,@BsParaID int,@StrBatchVal varchar(200),@StrVal varchar(200), @Type bigint, @Base int,@CompanyId int, @EffDate Date


    if exists (select 'x' from Tblbatchnosetting where baseprid=@BsProductID and PrCompID=@PrCompID and wcid=@WcID and effdate <= @CreationDt )
        Declare Cur_SttgMaster Cursor For Select RestartFrom,BatchID, Isnull(type,1),Base, CompanyId as Type,EffDate from Tblbatchnosetting where baseprid=@BsProductID and PrCompID=@PrCompID and wcid=@WcID 
        and effdate <= @CreationDt order by effdate desc
    else
    begin
        Declare Cur_SttgMaster Cursor For Select RestartFrom,BatchID, Isnull(Type,1) as Type,Base,CompanyId,EffDate  from Tblbatchnosetting where Companyid in (Select MfgID from TblBaseProduct where BsProductID=@BsProductID) and Base=1 and PrCompID=@PrCompID and wcid=@WcID
        and effdate <= @CreationDt order by effdate desc
    end

    open Cur_SttgMaster
    Fetch Next From Cur_SttgMaster Into @RestartFrom, @BatchID, @Type, @Base, @CompanyId,@EffDate
    Close Cur_SttgMaster
    Deallocate Cur_SttgMaster
    Set @RetType = @Type

    If @RestartFrom <> 0
        begin
        if @Base=1 
        begin 
            if @RestartFrom=1   --- Month ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid  in (Select Bsproductid from TblBaseProduct where Mfgid=@CompanyId) and Wcid=@Wcid 
                and fid=@Fid and month(CreatDate)=Month(@CreationDt)
            else if @RestartFrom=2  --- Yearly ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid in (Select Bsproductid from TblBaseProduct where Mfgid=@CompanyId) and Wcid=@Wcid 
                 and Year(CreatDate)=Year(@CreationDt) and CREATDATE >=@EffDate 
            else if @RestartFrom=3  --- never ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid in (Select Bsproductid from TblBaseProduct where Mfgid=@CompanyId) and Wcid=@Wcid 
        end 
        else if @Base=2
            BEGIN
            if @RestartFrom=1   --- Month ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid=@BsProductID and Wcid=@Wcid 
                and fid=@Fid and month(CreatDate)=Month(@CreationDt)
            else if @RestartFrom=2  --- Yearly ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid=@BsProductID and Wcid=@Wcid 
                and Year(CreatDate)=Year(@CreationDt) and CREATDATE >=@EffDate 
            else if @RestartFrom=3  --- Never ReStart
                Select @BatchMaxVal = isnull(Max(BatchNum),0) from tblbatchmaster where PrCompID=@PrCompID and BasePrid=@BsProductID and Wcid=@Wcid 
            END

            Declare Cur_SttgDetail Cursor For Select BsParaID,ParaType,BatchValue,BatchFormat,Digits from TblBatchNoSettingDetail where BatchID=@BatchID order by SeqNo

            Open Cur_SttgDetail
            Fetch Next From Cur_SttgDetail Into @BsParaID,@ParaType,@BatchValue,@BatchFormat,@Digits

            Set @StrVal=''
            While @@Fetch_Status=0
                begin
                    Set @StrBatchVal=''
                    if @BsParaID=6      -- for Year
                        begin
                            if upper(ltrim(rtrim(@BatchFormat)))='Y'
                                Set @StrBatchVal=Cast(Cast(right(year(@CreationDt),1)as int) as varchar(2))
                            else if upper(ltrim(rtrim(@Batchformat)))='YY'
                                Set @StrBatchVal=Cast(right(year(@CreationDt),2) as varchar(2))
                            else if upper(ltrim(rtrim(@Batchformat)))='YYYY'
                                Set @StrBatchVal=Cast(year(@CreationDt) as varchar(4))
                        end
                    else if @BsParaID=7 -- For Month
                        begin
                            if upper(ltrim(rtrim(@BatchFormat)))='MM'
                                if Cast(month(@CreationDt) as int) < 10
                                    Set @StrBatchVal= '0' + Cast(month(@CreationDt)as varchar(2))
                                else
                                    Set @StrBatchVal= Cast(month(@CreationDt)as varchar(2))
                            else if Upper(ltrim(rtrim(@BatchFormat)))='A'
                                Set @StrBatchVal=(Select Case cast(Month(@CreationDt)as int) 
                                    when 1 then 'A'
                                    when 2 then 'B'
                                    when 3 then 'C'
                                    when 4 then 'D'
                                    when 5 then 'E'
                                    when 6 then 'F'
                                    when 7 then 'G'
                                    when 8 then 'H'
                                    when 9 then 'I'
                                    when 10 then'J'
                                    when 11 then'K'
                                    when 12 then'L' 
                                end)

                        end
                    else if @BsParaID=8
                        begin
                            if @BatchMaxVal=0
                            begin
                                if @RestartFrom=3 
                                   begin 
                                    if @Batchvalue>=100
                                        begin 
                                            Set @StrBatchVal = @BatchValue
                                            Set @BatchNum=Cast(@BatchValue as bigint)
                                        end
                                        else
                                        begin
                                            Set @StrBatchVal = Cast(replicate('0',@Digits-len(@BatchValue)) as varchar(10)) + @BatchValue
                                            Set @BatchNum=Cast(@BatchValue as bigint)
                                        end 
                                    end 
                                else
                                begin 
                                    Set @StrBatchVal = Cast(replicate('0',@Digits-len(@BatchValue)) as varchar(10)) + @BatchValue
                                    Set @BatchNum=Cast(@BatchValue as bigint)
                                end 
                            end
                            else
                            begin
                                    Set @BatchMaxVal=@BatchMaxVal+1                         
                                    Set @StrBatchVal = cast(replicate('0',@Digits-len(cast(@BatchMaxVal as varchar(10)))) as varchar(10)) + Cast(@BatchMaxVal as varchar(10))
                                    Set @BatchNum=@BatchMaxVal
                            end
                        end
                    if @StrBatchVal=''
                        Set @StrBatchVal=@BatchValue
                    Set @StrVal = @StrVal + @StrBatchVal
                    Fetch Next From Cur_SttgDetail Into @BsParaID,@ParaType,@BatchValue,@BatchFormat,@Digits
                end
            Close Cur_SttgDetail
            Deallocate Cur_SttgDetail
            Set @StrBatchNo = cast(@StrVal as varchar(200))         
        end
        Return @RetType
        Return @BatchNum 
        Return @StrBatchNo
end

你能告诉我如何调用这个我尝试但失败的存储过程

                string strsql = "Exec [dbo].[GENRATE_BATCHNO] " + Fid + "," + WcID + "," + PrCompID + "," + BsProductID + ",'" + CreationDate + "' ";
                Reader = dc.GetReader(strsql);

【问题讨论】:

天哪 - 多么巨大的混乱!你真的要convert这个吗?我会折腾它并尝试再次从头开始编写它 - 没有所有这些游标! 起点:阅读official MSDN SQL Server Books Online documentation on how to create a table-valued function - 基本上你需要有一个SELECT,你可以从该函数返回一个TABLE 【参考方案1】:

有两种方法

将您的 sp 重写为表值函数 (http://msdn.microsoft.com/en-us/library/ms187650.aspx)

使用丑陋的 OpenQuery 方式见下例

CREATE FUNCTION dbo.myfunction    
   (@f1 char(14), @d1 smalldatetime, @tip char(1))
RETURNS TABLE
AS
  RETURN
     (SELECT * FROM openquery('SERVER', 'exec dbo.sp @f1, @d1, @tip'))

【讨论】:

以上是关于如何将存储过程更改为表值函数?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server存储过程中使用表值作为输入参数示例

在使用表值参数时如何将多个参数一起传递给存储过程

存储过程和表值函数有啥区别?

如何从.net代码将表值参数传递给存储过程

SQL Server:表值函数与存储过程

将表值参数传递给具有不同字段数的存储过程