使用多个参数进行搜索

时间:2012-07-25 10:00:13

标签: sql sql-server

我想搜索有关订单详情的信息。

where @SDateMin as ShipDateMin and @SDateMax as ShipDateMax,

等。

但是当我执行我的存储过程时,我收到错误:

  

Msg 137,Level 15,State 2,Line 8
  必须声明标量变量“@spmin”

我的T-SQL代码是:

ALTER PROC sp_SearchOrderDetails
@FName NVARCHAR(30) = NULL,
@LName NVARCHAR(30)= NULL,
@Status BIT = NULL ,
@SDateMin nvarchar(50) = NULL,
@SDateMax nvarchar(50) = NULL,
@ODateMin nvarchar(50) = NULL,
@ODateMax nvarchar(50) = NULL
AS
BEGIN
 DECLARE @SqlStr NVARCHAR(MAX), 
         @ParamList NVARCHAR(2000)
 SELECT @SqlStr = 'SELECT O.* FROM dbo.OrderDetails O where (1=1)'
 IF @FName IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.FirstName like''%' + @FName + '%'')'
 IF @LName IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.LastName like''%' + @LName + '%'')'
If @SDateMin IS NOT NULL  AND @SDateMax IS NOT NULL
        DECLARE @spmin DATE =  Convert(DATE,@SDateMin,105)
        DECLARE @spmax DATE =  Convert(DATE,@SDateMax,105)
        SELECT @SqlStr = @SqlStr + 'AND ( O.ShipDate BETWEEN @spmin AND @spmax )'   
If @ODateMin IS NOT NULL AND @ODateMax IS NOT NULL
        DECLARE @odmin DATE =  Convert(DATE,@ODateMin,105)
        DECLARE @odmax DATE =  Convert(DATE,@ODateMax,105)
        SELECT @SqlStr = @SqlStr + 'AND ( O.OrderDate BETWEEN @odmin AND  @odmax )'
If @Status IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.ShipStatus = @Status )'
SELECT @ParamList = '
        @FName nvarchar(30),
        @LName nvarchar(30),
        @Status bit,
        @SDateMin nvarchar(50),
        @SDateMax nvarchar(50),
        @ODateMin nvarchar(50),
        @ODateMax nvarchar(50)'
EXEC SP_EXECUTESQL  @SqlStr,
                    @ParamList,
                    @FName,
                    @LName ,
                    @Status,
                    @SDateMin,
                    @SDateMax,
                    @ODateMin,
                    @ODateMax
END

exec:

   DECLARE  @return_value int

EXEC    @return_value = [dbo].[sp_SearchOrderDetails]
        @SDateMin = N'10-10-2011',
        @SDateMax = N'10-10-2012'

SELECT  'Return Value' = @return_value

GO




CREATE TABLE [dbo].[OrderDetails](
    [OrderDetailId] [int] IDENTITY(1,1) NOT NULL,
    [CustomerTitle] [nvarchar](5) NOT NULL,
    [FirstName] [nvarchar](18) NOT NULL,
    [LastName] [nvarchar](22) NOT NULL,
    [PhoneNumber] [nvarchar](15) NOT NULL,
    [Email] [nvarchar](30) NOT NULL,
    [Address] [nvarchar](60) NOT NULL,
    [Country] [nvarchar](20) NOT NULL,
    [ShipStatus] [bit] NOT NULL,
    [OrderDate] [datetime] NOT NULL,
    [ShipDate] [datetime] NOT NULL,
    [PaymentProvider] [nvarchar](20) NOT NULL,
    [Deliver] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_OrderDetails] PRIMARY KEY CLUSTERED 
(
    [OrderDetailId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

1 个答案:

答案 0 :(得分:0)

@ParamList包含在过程声明中命名的参数,但稍后会引入另一个类似命名的变量。我也改变了数据类型,因为convert表明它们实际上是日期。

SELECT @ParamList = '
        @FName nvarchar(30),
        @LName nvarchar(30),
        @Status bit,
        @spmin date,
        @spmax date,
        @odmin date,
        @odmax date'

编辑:我不明白你最后的评论。要解决您的问题,您需要在begin ... end块中包含IF后的代码。

ALTER PROC sp_SearchOrderDetails
@FName NVARCHAR(30) = NULL,
@LName NVARCHAR(30)= NULL,
@Status BIT = NULL ,
@SDateMin nvarchar(50) = NULL,
@SDateMax nvarchar(50) = NULL,
@ODateMin nvarchar(50) = NULL,
@ODateMax nvarchar(50) = NULL
AS
BEGIN
 DECLARE @SqlStr NVARCHAR(MAX), 
         @ParamList NVARCHAR(2000)
 SELECT @SqlStr = 'SELECT O.* FROM dbo.OrderDetails O where (1=1)'
 IF @FName IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.FirstName like''%' + @FName + '%'')'
 IF @LName IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.LastName like''%' + @LName + '%'')'
If @SDateMin IS NOT NULL  AND @SDateMax IS NOT NULL
BEGIN
        DECLARE @spmin DATE =  Convert(DATE,@SDateMin,105)
        DECLARE @spmax DATE =  Convert(DATE,@SDateMax,105)
        SELECT @SqlStr = @SqlStr + 'AND ( O.ShipDate BETWEEN @spmin AND @spmax )'   
END
If @ODateMin IS NOT NULL AND @ODateMax IS NOT NULL
BEGIN
        DECLARE @odmin DATE =  Convert(DATE,@ODateMin,105)
        DECLARE @odmax DATE =  Convert(DATE,@ODateMax,105)
        SELECT @SqlStr = @SqlStr + 'AND ( O.OrderDate BETWEEN @odmin AND  @odmax )'
END
If @Status IS NOT NULL
    SELECT @SqlStr = @SqlStr + 'AND ( O.ShipStatus = @Status )'
SELECT @ParamList = '
        @FName nvarchar(30),
        @LName nvarchar(30),
        @Status bit,
        @spmin date,
        @spmax date,
        @odmin date,
        @odmax date'

EXEC SP_EXECUTESQL  @SqlStr,
                    @ParamList,
                    @FName,
                    @LName ,
                    @Status,
                    @spmin,
                    @spmax,
                    @odmin,
                    @odmax
END

我建议你这样做,即使后面只有一行,因为你永远不知道什么时候你必须扩展它,并且很容易忘记在那个时候开始和结束新代码,因为你正在解决其他问题,而不是校对。