存储过程日期自和

时间:2016-04-03 22:03:11

标签: sql-server date stored-procedures

我正在尝试创建一个用于过滤订单的存储过程。基本上,用户可以选择按日期和日期过滤订单。因此,如果有意义,他们可以通过日期,日期或两者进行搜索吗?

无论如何这是我目前的SQL Server存储过程

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
    @CustomerID int,
    @OrderItemWRClass varchar(max) = NULL,
    @OrderItemSKUName varchar(50) = NULL,
    @OrderItemDateFrom Datetime,
    @OrderItemDateTo Datetime
AS
BEGIN
    SET NOCOUNT ON;

    IF DATEDIFF(d, @OrderItemDateFrom, '01/01/1970') = 0 
       SET @OrderItemDateFrom = null 
    IF DATEDIFF(d, @OrderItemDateTo, '01/01/1970') = 0 
       SET @OrderItemDateTo = null 

    -- Insert statements for procedure here
    SELECT 
        COM_OrderItem.OrderItemID, COM_Order.OrderID, 
        COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
        COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
        COM_OrderItem.OrderItemSKUID
    FROM 
        COM_OrderItem
    INNER JOIN 
        COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
    WHERE  
        COM_Order.OrderCustomerID = @CustomerID 
        OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
        OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%'
        OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE @OrderItemDateFrom + '%' 
    ORDER BY 
        COM_Order.OrderDate DESC

但是我不确定如何在最终的SQL语句中将日期从(OrderItemDateFrom)和日期放到(OrderItemDateTo)?

我应该使用OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE @OrderItemDateFrom + '%' - 这会给我一个错误

  

从字符串转换日期和/或时间时转换失败。

我知道在普通的SQL查询中我会使用Between OrderItemDateFrom and OrderItemDateTo

由于

3 个答案:

答案 0 :(得分:0)

使用此逻辑

    ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
-- Add the parameters for the stored procedure here
@CustomerID int,
@OrderItemWRClass varchar(max) = NULL,
@OrderItemSKUName varchar(50) = NULL,
@OrderItemDateFrom Datetime,
@OrderItemDateTo Datetime
AS
BEGIN

SET NOCOUNT ON;

IF DATEDIFF(d,@OrderItemDateFrom,'01/01/1970')=0 SET @OrderItemDateFrom = '01/01/1970';
IF DATEDIFF(d,@OrderItemDateTo,'01/01/1970')=0 SET @OrderItemDateTo = '31/12/2199';

-- Insert statements for procedure here
SELECT COM_OrderItem.OrderItemID, COM_Order.OrderID, COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
COM_OrderItem.OrderItemSKUID
FROM COM_OrderItem
INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE COM_Order.OrderCustomerID = @CustomerID OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%'
OR (COM_OrderDate>=@OrderItemDateFrom && COM_OrderDate<=@OrderItemDateTo ) 
ORDER BY COM_Order.OrderDate DESC

试试吧。它应该工作。

答案 1 :(得分:0)

通过允许@OrderItemDateFrom@OrderItemDateTo的NULL值,可以简化您的逻辑。此外,如果过滤器值和列值都是DATETIME s,则应尝试直接比较以允许索引使用(如果在DATETIME列上应用任何值):

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
    @CustomerID int,
    @OrderItemWRClass varchar(max) = NULL,
    @OrderItemSKUName varchar(50) = NULL,
    @OrderItemDateFrom Datetime = NULL, -- TODO: change caller to not provide parameter, or leave it to null
    @OrderItemDateTo Datetime = NULL    -- TODO: change caller to not provide parameter, or leave it to null
AS
BEGIN
    SET NOCOUNT ON;

    -- when working with dates try to use an unambiguous format like 'YYYY-MM-DD'
    SET @OrderItemDateFrom = ISNULL(@OrderItemDateFrom, '1970-01-01')
    -- assign a very large date to act like not provided
    -- going one day after to catch DATETIMEs with provided time
    SET @OrderItemDateTo = DATEADD(day, 1, ISNULL(@OrderItemDateTo, '3000-01-01'))

    -- Insert statements for procedure here
    SELECT 
        COM_OrderItem.OrderItemID, COM_Order.OrderID, 
        COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
        COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
        COM_OrderItem.OrderItemSKUID
    FROM COM_OrderItem
    INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
    WHERE COM_Order.OrderCustomerID = @CustomerID 
        OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
        OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%'
        -- between can be used
        OR (COM_OrderDate BETWEEN @OrderItemDateFrom AND @OrderItemDateTo)
    ORDER BY 
        COM_Order.OrderDate DESC
END

另一种选择是使用动态SQL并根据参数值构造它(即,如果提供了过滤值,则插入WHERE条件)。当过滤器数量与过滤器总数相比相对较低时,这尤其有用,因为OR s对性能不友好。

注意:不应该结合使用过滤器(即使用AND代替OR)?允许用户在同一时间过滤几个值是有意义的。

答案 2 :(得分:0)

ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
@CustomerID int,
@OrderItemWRClass varchar(max) = NULL,
@OrderItemSKUName varchar(50) = NULL,
@OrderItemDateFrom Datetime,
@OrderItemDateTo Datetime
AS
BEGIN
SET NOCOUNT ON;

IF DATEDIFF(d, @OrderItemDateFrom, '01/01/1970') = 0 
   SET @OrderItemDateFrom = null 
IF DATEDIFF(d, @OrderItemDateTo, '01/01/1970') = 0 
   SET @OrderItemDateTo = null 

-- Insert statements for procedure here
SELECT 
    COM_OrderItem.OrderItemID, COM_Order.OrderID, 
    COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, 
    COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
    COM_OrderItem.OrderItemSKUID
FROM 
    COM_OrderItem
INNER JOIN 
    COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE  
    COM_Order.OrderCustomerID = @CustomerID 
    OR COM_OrderItem.OrderItemWRClass LIKE @OrderItemWRClass + '%' 
    OR COM_OrderItem.OrderItemSKUName LIKE @OrderItemSKUName + '%'
    OR (@OrderItemDateFrom IS NULL OR COM_Order.OrderDate >=@OrderItemDateFrom)
    OR (@OrderItemDateTo IS NULL OR COM_Order.OrderDate <=@OrderItemDateTo)
ORDER BY 
    COM_Order.OrderDate DESC

你应该试试这个。

OR (@OrderItemDateFrom IS NULL OR COM_Order.OrderDate >=@OrderItemDateFrom)
OR (@OrderItemDateTo IS NULL OR COM_Order.OrderDate <=@OrderItemDateTo)

只需编辑并尝试此条件..