【问题标题】:ISDATE producing error for DATE (datatype) valueISDATE 为 DATE(数据类型)值产生错误
【发布时间】:2018-08-06 17:14:49
【问题描述】:

我在 My_Table 中有一个 MyDate(datatype DATE) 列

MyDate
2016-11-01
0001-01-01
2016-08-01

当我执行以下查询时

SELECT  ISDATE(MyDate),* FROM My_Table

我收到以下错误

消息 8116,级别 16,状态 1,行 2 参数数据类型日期无效 用于 isdate 函数的参数 1。

我认为问题可能是日期'0001-01-01'。但是当我执行

SELECT ISDATE('0001-01-01')

它按预期工作并产生了结果0。(即不是日期)

但是

DECLARE @V AS DATE = '0001-01-01' --no error
SELECT ISDATE(@V) --error

这会产生同样的错误。 我哪里错了?

编辑:- 如果我从 Mytable 中删除值 '0001-01-01',则查询 SELECT ISDATE(MyDate) 无需任何数据类型转换即可正常工作。

【问题讨论】:

  • 为什么要对数据类型为 DATE 的列使用 ISDATE?你认为在什么情况下它会返回 FALSE?
  • @MartinSmith,如果 ISADTE('0001-01-01') 也返回 TRUE 则可以,我可以理解,then why this error for date value?
  • @AbdulRasheed 因为函数ISDATE 需要可以转换为字符串的字符串或表达式。由于Data Type Precedence,日期不会被转换成字符串
  • 对于您要达到的目标,这里肯定存在一些混淆。根据定义date 列中包含的任何内容都是有效日期。在你开始编写这段代码之前,你打算做什么?
  • 你现在最重要的问题是为什么开发人员选择不花时间让你使用一个函数来提出一个唯一可能答案是肯定的问题?如果不是,请首先解释是什么导致您尝试在date 值上调用ISDATE,我们或许能够提供实际帮助。否则,这只是琐事。

标签: sql-server tsql


【解决方案1】:

请注意,Sarthak Grover 的 answer 准确说明了您收到语法错误的原因。我只是发布了我的答案来详细说明一下,并解释为什么isdate('0001-01-01') 返回false,当它是Date 数据类型的完全有效值时。

ISDATE 函数的全部意义在于确定在当前DATEFORMAT 设置下,参数是否可以转换为有效的DatetimeDateTime,只需使用cast (相对于convert,它接受样式参数,因此不依赖于当前的日期格式设置。
DATE 类型的参数传递给ISDATE 函数是没有意义的,因为如果参数的类型是DATE,则无需检查它。

此外,明确禁止传递日期和时间数据类型的参数,datetimesmalldatetime 除外,正如 Sarthak Grover 在他的 answer 中指出的那样(+1 来自我,顺便说一句)。

ISDATE 函数将返回 false,即使参数可转换为日期值,如果它表示 1753-01-01 之前或 9999-12-31 之后的日期值。
这是因为DATETIME数据类型的取值范围是从1753-01-01 00:00:009999-12-31 23:59:59.997

这是一个简单的演示(try it yourself on rextester):

DECLARE @T AS TABLE
(
    DateString varchar(20),
    Comments varchar(100)
);

INSERT INTO @T (DateString, Comments) VALUES
('1752-12-31', 'will always return false'),
('1753-01-01', 'will always return true'),
('2018-02-27', 'depends on dateformat'),
('2018-27-02', 'depends on dateformat');

SET DATEFORMAT YMD;

SELECT  DateString, 
        Comments, 
        ISDATE(DateString) As IsDate
FROM @T;

SET DATEFORMAT YDM;

SELECT  DateString, 
        Comments, 
        ISDATE(DateString) As IsDate
FROM @T;

结果:

DateString      Comments                    IsDate
1752-12-31      will always return false    0
1753-01-01      will always return true     1
2018-02-27      depends on dateformat       1
2018-27-02      depends on dateformat       0

DateString      Comments                    IsDate
1752-12-31      will always return false    0
1753-01-01      will always return true     1
2018-02-27      depends on dateformat       0
2018-27-02      depends on dateformat       1

【讨论】:

  • 谢谢,但在这里我没有得到 FALSE/TRUE 结果,而是错误。即使ISDATE('ABC') 也不会产生错误。
  • 因为您将 date 日期类型传递给 isdate 函数,这是明确禁止的。我仍在努力寻找答案,很快就会有更多详细信息。
  • SELECT ISDATE(CAST(MyDate AS VARCHAR)),* FROM TBL 在这里,您将值转换为 Varchar,然后比较该值是否为有效日期
【解决方案2】:

ISDATE(表达式)

参数

表达式 是可以转换为字符串的字符串或表达式。表达式必须少于 4,000 个字符。 日期和时间数据类型(datetime 和 smalldatetime 除外)不允许作为 ISDATE 的参数。

来源:https://docs.microsoft.com/en-us/sql/t-sql/functions/isdate-transact-sql

【讨论】:

  • 我的列不是 NULL DATE 字段,如果我删除值 '0001-01-01' 查询 ISDATE(MyDate) 将在没有任何转换的情况下工作。
【解决方案3】:

ISDATE() 只能评估 STRING,所以试试这样。

DECLARE @V DATE = '0001-01-01'
SELECT ISDATE(CAST(@V AS VARCHAR(30))) 

【讨论】:

  • 顺便提一下,ISDATE 对日期字符串 0001-01-01 返回 false,但这可能与内部逻辑有关,与 OP 无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多