Sql 将特定的日期格式数据限制到表中

Sql 将特定的日期格式数据限制到表中,sql,sql-server,sql-server-2005,tsql,sql-server-2008,Sql,Sql Server,Sql Server 2005,Tsql,Sql Server 2008,我有一个名为Sur_Data的表,数据如下所示: ID SV_Date 258 13/01/2010 569 15/02/2011 695 26/05/2010 745 12/06/2010 现在,我想从该表中选择ID并插入到另一个表中,因此我们使用类似于: Insert into Surdate(ID) Select ID from Sur_Data where ISDATE(SV_Date) = 1 由于SV_Date中的格式不同,因此不会将任何记录插入S

我有一个名为Sur_Data的表,数据如下所示:

ID     SV_Date
258    13/01/2010
569    15/02/2011
695    26/05/2010
745    12/06/2010
现在,我想从该表中选择ID并插入到另一个表中,因此我们使用类似于:

Insert into Surdate(ID)
Select ID from Sur_Data
where ISDATE(SV_Date) = 1
由于SV_Date中的格式不同,因此不会将任何记录插入Surdate表中

所以我想看看是否有一种方法可以限制Sur_data表中的数据只有MM/DD/YYYY格式的日期。因此,每当他们试图插入不同格式的记录时,都会抛出一个错误


有人能帮忙吗?

要严格回答这个问题,您可以创建一个函数(CLR或TSQL)并将其作为列约束/检查应用

但正如@joe Stefanelli正确指出的,将其存储为datetime数据类型,并让客户机处理表示格式

编辑


它假设您定义了一个函数,如果格式符合预期,则返回1。

编辑:例如2和3,ANSI警告必须关闭

IS_DATE
函数受当前SQL Server会话/连接的
DATEFORMAT
设置的影响

示例1:

DECLARE @d1 VARCHAR(25) = '26/05/2010'
        ,@d2 VARCHAR(25) = '15/02/2011';

PRINT '*****Test 1*****'        
SET DATEFORMAT DMY;
SELECT  ISDATE(@d1), ISDATE(@d2);       

PRINT '*****Test 2*****'        
SET DATEFORMAT MDY;
SELECT  ISDATE(@d1), ISDATE(@d2);
SET ANSI_WARNINGS OFF;
SET ARITHABORT OFF;

DECLARE @Results TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
);

INSERT  @Results 
VALUES
 (258,    '13/01/2010')
,(569,    '15/02/2011')
,(695,    '26/05/2010')
,(745,    '12/06/2010');

SELECT  *
        ,ISDATE(r.SV_Date) [IS_DATETIME]
        ,CONVERT(DATETIME,r.SV_Date,103) [IS_DATETIME British/French style=dd/mm/yyyy]
        ,CONVERT(DATETIME,r.SV_Date,101) [IS_DATETIME U.S. style=mm/dd/yyyy]
        ,CASE 
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_DMY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_DMY_OR_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_NOT_DMY_OR_MDY'
        END
FROM    @Results r;
DECLARE @Results2 TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
    ,CHECK( CONVERT(DATETIME,SV_Date,101) IS NOT NULL )
);
SET ANSI_WARNINGS OFF;
INSERT  @Results2 
VALUES  (258,    '13/01/2010');
INSERT  @Results2 
VALUES  (569,    '15/02/2011');
INSERT  @Results2 
VALUES  (695,    '26/05/2010');
INSERT  @Results2 
VALUES  (745,    '12/06/2010');
SELECT  *
FROM    @Results2;
结果:

*****Test 1*****

----------- -----------
1           1

(1 row(s) affected)

*****Test 2*****

----------- -----------
0           0

(1 row(s) affected)
ID          SV_Date              IS_DATETIME IS_DATETIME British/French style=dd/mm/yyyy IS_DATETIME U.S. style=mm/dd/yyyy 
----------- -------------------- ----------- ------------------------------------------- --------------------------------- -----------------
258         13/01/2010           0           2010-01-13 00:00:00.000                     NULL                              IS_DMY
569         15/02/2011           0           2011-02-15 00:00:00.000                     NULL                              IS_DMY
695         26/05/2010           0           2010-05-26 00:00:00.000                     NULL                              IS_DMY
745         12/06/2010           1           2010-06-12 00:00:00.000                     2010-12-06 00:00:00.000           IS_DMY_OR_MDY
ID          SV_Date
----------- --------------------
745         12/06/2010

(1 row(s) affected)
现在,您可以看到
DATEFORMAT
如何影响
ISDATE
函数。 您可以使用具有不同属性的
CONVERT
函数,而不是
ISDATE
函数。如果
[n][var]char
值没有选定的样式,则
CONVERT
函数将返回NULL。对于
dd/mm/yyyy
值(英国)可以使用样式103,对于
mm/dd/yyyy
值(美国)可以使用样式101

示例2:

DECLARE @d1 VARCHAR(25) = '26/05/2010'
        ,@d2 VARCHAR(25) = '15/02/2011';

PRINT '*****Test 1*****'        
SET DATEFORMAT DMY;
SELECT  ISDATE(@d1), ISDATE(@d2);       

PRINT '*****Test 2*****'        
SET DATEFORMAT MDY;
SELECT  ISDATE(@d1), ISDATE(@d2);
SET ANSI_WARNINGS OFF;
SET ARITHABORT OFF;

DECLARE @Results TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
);

INSERT  @Results 
VALUES
 (258,    '13/01/2010')
,(569,    '15/02/2011')
,(695,    '26/05/2010')
,(745,    '12/06/2010');

SELECT  *
        ,ISDATE(r.SV_Date) [IS_DATETIME]
        ,CONVERT(DATETIME,r.SV_Date,103) [IS_DATETIME British/French style=dd/mm/yyyy]
        ,CONVERT(DATETIME,r.SV_Date,101) [IS_DATETIME U.S. style=mm/dd/yyyy]
        ,CASE 
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_DMY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_DMY_OR_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_NOT_DMY_OR_MDY'
        END
FROM    @Results r;
DECLARE @Results2 TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
    ,CHECK( CONVERT(DATETIME,SV_Date,101) IS NOT NULL )
);
SET ANSI_WARNINGS OFF;
INSERT  @Results2 
VALUES  (258,    '13/01/2010');
INSERT  @Results2 
VALUES  (569,    '15/02/2011');
INSERT  @Results2 
VALUES  (695,    '26/05/2010');
INSERT  @Results2 
VALUES  (745,    '12/06/2010');
SELECT  *
FROM    @Results2;
结果:

*****Test 1*****

----------- -----------
1           1

(1 row(s) affected)

*****Test 2*****

----------- -----------
0           0

(1 row(s) affected)
ID          SV_Date              IS_DATETIME IS_DATETIME British/French style=dd/mm/yyyy IS_DATETIME U.S. style=mm/dd/yyyy 
----------- -------------------- ----------- ------------------------------------------- --------------------------------- -----------------
258         13/01/2010           0           2010-01-13 00:00:00.000                     NULL                              IS_DMY
569         15/02/2011           0           2011-02-15 00:00:00.000                     NULL                              IS_DMY
695         26/05/2010           0           2010-05-26 00:00:00.000                     NULL                              IS_DMY
745         12/06/2010           1           2010-06-12 00:00:00.000                     2010-12-06 00:00:00.000           IS_DMY_OR_MDY
ID          SV_Date
----------- --------------------
745         12/06/2010

(1 row(s) affected)
现在,如果要检查
mm/dd/yyyy
格式(样式101-美国)的SV_日期值,则可以使用如下约束:

示例3:

DECLARE @d1 VARCHAR(25) = '26/05/2010'
        ,@d2 VARCHAR(25) = '15/02/2011';

PRINT '*****Test 1*****'        
SET DATEFORMAT DMY;
SELECT  ISDATE(@d1), ISDATE(@d2);       

PRINT '*****Test 2*****'        
SET DATEFORMAT MDY;
SELECT  ISDATE(@d1), ISDATE(@d2);
SET ANSI_WARNINGS OFF;
SET ARITHABORT OFF;

DECLARE @Results TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
);

INSERT  @Results 
VALUES
 (258,    '13/01/2010')
,(569,    '15/02/2011')
,(695,    '26/05/2010')
,(745,    '12/06/2010');

SELECT  *
        ,ISDATE(r.SV_Date) [IS_DATETIME]
        ,CONVERT(DATETIME,r.SV_Date,103) [IS_DATETIME British/French style=dd/mm/yyyy]
        ,CONVERT(DATETIME,r.SV_Date,101) [IS_DATETIME U.S. style=mm/dd/yyyy]
        ,CASE 
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_DMY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NOT NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NOT NULL THEN 'IS_DMY_OR_MDY'
            WHEN CONVERT(DATETIME,r.SV_Date,103) IS NULL AND CONVERT(DATETIME,r.SV_Date,101) IS NULL THEN 'IS_NOT_DMY_OR_MDY'
        END
FROM    @Results r;
DECLARE @Results2 TABLE
(
    ID INT PRIMARY KEY
    ,SV_Date VARCHAR(20) NOT NULL
    ,CHECK( CONVERT(DATETIME,SV_Date,101) IS NOT NULL )
);
SET ANSI_WARNINGS OFF;
INSERT  @Results2 
VALUES  (258,    '13/01/2010');
INSERT  @Results2 
VALUES  (569,    '15/02/2011');
INSERT  @Results2 
VALUES  (695,    '26/05/2010');
INSERT  @Results2 
VALUES  (745,    '12/06/2010');
SELECT  *
FROM    @Results2;
结果:

*****Test 1*****

----------- -----------
1           1

(1 row(s) affected)

*****Test 2*****

----------- -----------
0           0

(1 row(s) affected)
ID          SV_Date              IS_DATETIME IS_DATETIME British/French style=dd/mm/yyyy IS_DATETIME U.S. style=mm/dd/yyyy 
----------- -------------------- ----------- ------------------------------------------- --------------------------------- -----------------
258         13/01/2010           0           2010-01-13 00:00:00.000                     NULL                              IS_DMY
569         15/02/2011           0           2011-02-15 00:00:00.000                     NULL                              IS_DMY
695         26/05/2010           0           2010-05-26 00:00:00.000                     NULL                              IS_DMY
745         12/06/2010           1           2010-06-12 00:00:00.000                     2010-12-06 00:00:00.000           IS_DMY_OR_MDY
ID          SV_Date
----------- --------------------
745         12/06/2010

(1 row(s) affected)
意见: 如果要查找当前
DATEFORMAT
设置(当前会话),则可以使用:


为什么不为
SV_Date
列使用适当的(或2008年)数据类型?@JoeStefanelli I I am,但也将插入2010年5月26日、2011年2月15日等日期,但当我使用isdate()时在这些表上,它将返回0,并且不会插入到另一个表中。在插入/更新之前,在表上设置一个触发器,将日期转换为所需的格式如何?@Peter-datetime列不会有“格式”。我想你有些困惑。如果您的列给您的内容表明它不是日期,那么您就没有使用datetime列数据类型。@Peter:a
datetime
列是一个
datetime
列是一个
datetime
列-它没有任何“格式”或任何概念-它只是一个值。仅当在SQL Server Mgmt Studio或您的应用程序中显示此类数据时,格式才会起作用。有关更多详细信息,请参阅扫描您告诉我如何应用约束/检查?更新了示例和链接以更改表语法+1巧妙地使用转换函数和datetime。我从来没有意识到它有这个功能。@Bogdan当我执行它们时,我得到了一些错误,比如:Msg 242,级别16,状态3,第7行。将varchar数据类型转换为datetime数据类型会导致值超出范围。声明已终止。您测试了什么?您是否更改了数据类型?@Bogdan我对上述评论感到抱歉。但这正是我要找的。非常感谢你。谢谢你在这方面的帮助。@Peter:告诉我你举了什么例子?示例1/2/3?