首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

, 为何查不到想要的结果

2012-12-15 
高手请进, 为何查不到想要的结果想查 特定日期之间的数据, 不知这个函数有什么问题, 一直看不出来 。IF EXI

高手请进, 为何查不到想要的结果
想查 特定日期之间的数据, 不知这个函数有什么问题, 一直看不出来 。

IF EXISTS(
       SELECT *
       FROM   dbo.sysobjects
       WHERE  id = OBJECT_ID(N'[dbo].fn_ltDate')
              AND (TYPE = 'FN' OR TYPE = 'TF' OR TYPE = 'IF')
   )
BEGIN
    PRINT '已存在,删除再新建'
    DROP FUNCTION fn_ltDate
END
ELSE
BEGIN
    PRINT '不存在,新建'
END
GO

--新建函数
CREATE FUNCTION dbo.fn_ltDate
(
@startDate  VARCHAR(10),
@endDate    VARCHAR(10)
)
RETURNS BIT
AS
BEGIN
DECLARE @result BIT
SET @result = 0
IF (
       LTRIM(RTRIM(ISNULL(@startDate, ''))) = ''
       OR LTRIM(RTRIM(ISNULL(@endDate, ''))) = ''
       OR DATEDIFF(DAY, @startDate, @endDate) >= 0
   )
BEGIN
    SET @result = 1
END

RETURN @result
END
GO


DECLARE @TempTalbe TABLE (Id INT, CreateTime DATETIME)

INSERT INTO @TempTalbe
SELECT 1,
       '2012-1-2' UNION
SELECT 2,
       '2012-3-2' UNION
SELECT 3,
       '2012-4-2' UNION
SELECT 4,
       '2012-5-2' UNION
SELECT 5,
       '2012-6-2'

DECLARE @StartDate1 DATETIME 
DECLARE @EndDate1 DATETIME 
SET @StartDate1 = '2012-3-2'
SET @EndDate1 =''--为NULL就可以, 为''就不行

SELECT *
FROM   @TempTalbe t
WHERE  dbo.fn_ltDate(@StartDate1, CreateTime)=1
       AND 
       dbo.fn_ltDate(CreateTime, @EndDate1) = 1



[最优解释]
'' 轉換為datetime是 1900-01-01 00:00:00.000 

改成這樣
LTRIM(RTRIM(ISNULL(@startDate, '1900-01-01 00:00:00.000'))) = '1900-01-01 00:00:00.000'
           OR LTRIM(RTRIM(ISNULL(@endDate, '1900-01-01 00:00:00.000'))) = '1900-01-01 00:00:00.000'
           OR DATEDIFF(DAY, @startDate, @endDate) >= 0

[其他解释]
SELECT CAST('' AS DATETIME)
/*
1900-01-01 00:00:00.000

(1 行受影响)


*/

[其他解释]
這樣也行

LTRIM(RTRIM(ISNULL(@startDate, ''))) = '1900-1-1'
           OR LTRIM(RTRIM(ISNULL(@endDate, ''))) = '1900-1-1'
           OR DATEDIFF(DAY, @startDate, @endDate) >= 0


[其他解释]
引用:
同志们啊,我定义的只是字符串, 还没有到转换和比较的那一步嘛。
SQL code?12    @startDate  VARCHAR(10),    @endDate    VARCHAR(10)


我看到的是dateitime...

DECLARE @StartDate1 DATETIME 
DECLARE @EndDate1 DATETIME 
SET @StartDate1 = '2012-3-2'
SET @EndDate1 =''--为NULL就可以, 为''就不行

[其他解释]
CREATE FUNCTION dbo.fn_ltDate
(
    @startDate  VARCHAR(10),
    @endDate    VARCHAR(10)
)
RETURNS BIT
AS
BEGIN
    DECLARE @result BIT
    SET @result = 0
    IF (
           CONVERT(DATETIME,LTRIM(RTRIM(ISNULL(@startDate, '')))) = '1900-01-01 00:00:00.000'
           OR CONVERT(DATETIME,LTRIM(RTRIM(ISNULL(@endDate, '')))) = '1900-01-01 00:00:00.000'
           OR DATEDIFF(DAY, CONVERT(DATETIME,@startDate), CONVERT(DATETIME,@endDate)) >= 0
       )
    BEGIN
        SET @result = 1
    END
     
    RETURN @result
END
GO
 
 
DECLARE @TempTalbe TABLE (Id INT, CreateTime DATETIME)
 
INSERT INTO @TempTalbe
SELECT 1,
       '2012-1-2' UNION
SELECT 2,
       '2012-3-2' UNION
SELECT 3,
       '2012-4-2' UNION
SELECT 4,
       '2012-5-2' UNION
SELECT 5,
       '2012-6-2'
 
DECLARE @StartDate1 DATETIME 
DECLARE @EndDate1 DATETIME 
SET @StartDate1 = '2012-3-2'
SET @EndDate1 =''--为NULL就可以, 为''就不行

SELECT *
FROM   @TempTalbe t
WHERE  dbo.fn_ltDate(@StartDate1, CreateTime)=1
       AND 
       dbo.fn_ltDate(CreateTime, @EndDate1) = 1
[其他解释]
请看上面代码中的第 59 行: SET @EndDate1 =''--为NULL就可以, 为''就不行
[其他解释]
同志们啊,我定义的只是字符串, 还没有到转换和比较的那一步嘛。

    @startDate  VARCHAR(10),
    @endDate    VARCHAR(10)



[其他解释]
引用:
引用:同志们啊,我定义的只是字符串, 还没有到转换和比较的那一步嘛。
SQL code?12    @startDate  VARCHAR(10),    @endDate    VARCHAR(10)

我看到的是dateitime...
SQL code?1234DECLARE @StartDate1 DATETIME DECL……



楼主的哥们很细心, 发现了我的错误。 
当然喽, 也不算什么错误, 只算是我的函数设计的有bug吧——只能传varchar型的实参,不能传datetime型。 

#7的写法也很好,只是可读性差了一点点, 下面是本人修改后的。

在很多系统中, 根据日期范围来查询是很常见的操作。表单中输入 2012-05-01 到 2012-10-01
, 很容易漏掉 2012-10-01 这一天的记录, 而且总要判断 is null 或者空串等也比较麻烦, 故写了这段函数。 谢谢诸位, 希望对诸君有用。


IF EXISTS(
       SELECT *
       FROM   dbo.sysobjects
       WHERE  id = OBJECT_ID(N'[dbo].fn_ltDate')
              AND (TYPE = 'FN' OR TYPE = 'TF' OR TYPE = 'IF')
   )
BEGIN
    PRINT '已存在,删除再新建'
    DROP FUNCTION fn_ltDate
END
ELSE
BEGIN
    PRINT '不存在,新建'
END
GO
 
--Create   by: yenange
--Description: 前日期是否<=后面的日期(在同一天也算是小于等于)
--Parameters : @startDate 前日期,@endDate 后日期.
--             两参数传入时的类型可为 varchar 或者 datetime 型
--             若有一参数为null或者'', 则返回1 (也算是小于等于)
--Return     : 是 1 否 0
CREATE FUNCTION dbo.fn_ltDate
(
@startDate  VARCHAR(10),
@endDate    VARCHAR(10)
)
RETURNS BIT
AS
BEGIN
DECLARE @result BIT
SET @result = 0
IF (
       LTRIM(RTRIM(ISNULL(@startDate, ''))) = ''
       OR LTRIM(RTRIM(ISNULL(@endDate, ''))) = ''
       OR DATEDIFF(DAY, @startDate, '1900-01-01 00:00:00.000') = 0
       OR DATEDIFF(DAY, @endDate, '1900-01-01 00:00:00.000') = 0
       OR DATEDIFF(DAY, @startDate, @endDate) >= 0
   )
BEGIN
    SET @result = 1
END

RETURN @result
END
GO
 
DECLARE @TempTalbe TABLE (Id INT, CreateTime DATETIME)
INSERT INTO @TempTalbe
SELECT 1,'2012-1-2' UNION
SELECT 2,'2012-3-2 00:00:00' UNION
SELECT 3,'2012-4-2' UNION
SELECT 4,'2012-5-2 23:59:59' UNION
SELECT 5,'2012-6-2 23:59:59'

--参数为 datetime 型
DECLARE @StartDate1 DATETIME
DECLARE @EndDate1 DATETIME
SET @StartDate1 = '2012-3-2'
SET @EndDate1 = ''
 
SELECT *
FROM   @TempTalbe t
WHERE  dbo.fn_ltDate(@StartDate1, CreateTime) = 1
       AND dbo.fn_ltDate(CreateTime, @EndDate1) = 1

--参数为 varchar 型
DECLARE @StartDate2 VARCHAR(10)
DECLARE @EndDate2 VARCHAR(10)
SET @StartDate1 = '2012-3-2'
SET @EndDate1 = '2012-5-2'
SELECT *
FROM   @TempTalbe t
WHERE  dbo.fn_ltDate(@StartDate1, CreateTime) = 1
       AND dbo.fn_ltDate(CreateTime, @EndDate1) = 1





[其他解释]
引用:
引用:
引用:同志们啊,我定义的只是字符串, 还没有到转换和比较的那一步嘛。
SQL code?12    @startDate  VARCHAR(10),    @endDate    VARCHAR(10)

我看到的是dateitime...
SQL code?1234DECLARE @StartDate1 DATE……
其实日期中为''或者‘0’很容易疏忽,没有想到datetime格式的话就是默认的 '1900-01-01 00:00:00.000'

感谢分享。
           
[其他解释]
为什么函数不能传递datataime类型的参数?既然是日期,那何必要用varchar等字符串类型呢?

[其他解释]
引用:
为什么函数不能传递datataime类型的参数?既然是日期,那何必要用varchar等字符串类型呢?


最前面的不可以, #8可以(无论实际参数是datetime还是varchar)。

一个好的函数, 最好能有良好的兼容性。

即使你用 datetime 作形参, 人家还是可能传个空串进来, 所以形参用什么关系是不大的。

热点排行