Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server TSQL中不同日期格式的ISDATE函数_Sql Server_Sql Server 2008_Tsql_Datetime_Format - Fatal编程技术网

Sql server TSQL中不同日期格式的ISDATE函数

Sql server TSQL中不同日期格式的ISDATE函数,sql-server,sql-server-2008,tsql,datetime,format,Sql Server,Sql Server 2008,Tsql,Datetime,Format,我需要在视图的多列中将VARCHAR值转换为DATETIME,以便在SQL Server 2008上的另一个应用程序中进行排序和格式化(以区域设置格式显示) 目前有两个问题 VARCHAR值的输入格式不同(但在 列级别) 也可能存在错误值(例如:20..05.2015) 不幸的是,TRY_CONVERT函数仅适用于SQL Server 2012及更高版本 ISDATE不起作用,因为视图包含不同的日期格式,我既不能在用户定义的函数中也不能在视图中设置语言,这将导致ISDATE使用德语日期格式 我的

我需要在视图的多列中将
VARCHAR
值转换为
DATETIME
,以便在SQL Server 2008上的另一个应用程序中进行排序和格式化(以区域设置格式显示)

目前有两个问题

  • VARCHAR
    值的输入格式不同(但在 列级别)
  • 也可能存在错误值(例如:20..05.2015)
  • 不幸的是,TRY_CONVERT函数仅适用于SQL Server 2012及更高版本

    ISDATE
    不起作用,因为视图包含不同的日期格式,我既不能在用户定义的函数中也不能在视图中设置语言,这将导致
    ISDATE
    使用德语日期格式

    我的问题有没有更简单的解决办法? 我的第一个想法是写一个函数,比如

    FUNCTION TryConvertStringAsDatetime (   @value VARCHAR(MAX),
                                            @format INT
                                        )
    
    这使用了函数的格式编号,但是手动检查每种可能的格式让我有点害怕

    示例:TryConvertStringAsDatetime('20.05.2015',104)(带有一些伪代码)


    我可能会这样说:

    CREATE FUNCTION TryConvertToDate 
    (
        @InputString varchar(20)  
    )
    RETURNS Datetime
    BEGIN
        DECLARE @DateTime datetime = NULL
        SET @DateTime = 
           CASE 
               WHEN LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', @InputString)=1 THEN
                   CONVERT(DateTime, @InputString, 104) -- German
               WHEN LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', @InputString)=1 THEN
                   CONVERT(DateTime, @InputString, 120) -- ODBC
               ELSE
                   NULL -- unsuported format
           END
       RETURN @DateTime        
    END  
    
    注意:测试长度和使用确保只使用一般格式,因此您需要在try块中调用此函数,以防日期和月份颠倒,并导致转换错误。
    另一方面,将支持的格式添加到此函数非常简单-您所要做的就是添加一个
    when
    子句,该子句具有正确的
    patindex
    和长度以及正确的转换样式

    另一个选项是确保字符串可以实际转换为日期。
    这将使您的函数更复杂,因此更难编写,但更易于使用,因为它将使引发转换错误的可能性降至最低:

    CREATE FUNCTION TryConvertToDate 
    (
        @InputString varchar(20)  
    )
    RETURNS Datetime
    BEGIN
    
    
        DECLARE @DateValue date, @Days int, @Months int, @Years int
    
        IF LEN(@DateString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', @InputString)=1 -- German format
            BEGIN
                SELECT @Days = CAST(LEFT(@InputString, 2) As int),
                       @Months = CAST(SUBSTRING(@InputString, 4, 2) as int),
                       @Years = CAST(RIGHT(@InputString, 4) as int)
                -- NOTE: you will need to add a condition for leap years 
                IF (@Days < 31 AND @Months IN(4,6,9,12)) OR (@Days < 30 AND @Months = 2) 
                   SET @DateValue = convert(date, @InputString, 104)
            END
    
        IF LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', @InputString)=1 -- ODBC format
            BEGIN
                SELECT @Days = CAST(RIGHT(@InputString, 2) As int),
                       @Months = CAST(SUBSTRING(@InputString, 6, 2) as int),
                       @Years = CAST(LEFT(@InputString, 4) as int)
                -- NOTE: you will need to add a condition for leap years 
                IF (@Days < 31 AND @Months IN(4,6,9,12)) OR (@Days < 30 AND @Months = 2)
                   SET @DateValue = convert(date, @InputString, 120)
            END
    
        RETURN @DateValue
    
    END
    
    创建函数TryConvertToDate
    (
    @InputString varchar(20)
    )
    返回日期时间
    开始
    声明@DateValue-date、@Days-int、@Months-int、@Years-int
    如果LEN(@DateString)=10和PATINDEX('[0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9][0-9]',@InputString)=1--德语格式
    开始
    选择@Days=CAST(左(@InputString,2)作为int),
    @月份=强制转换(子字符串(@InputString,4,2)为int),
    @年份=强制转换(右(@InputString,4)为int)
    --注意:您需要为闰年添加一个条件
    如果(@Days<31和@Months IN(4,6,9,12))或(@Days<30和@Months=2)
    设置@DateValue=convert(日期,@InputString,104)
    终止
    如果LEN(@InputString)=10和PATINDEX('[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]',@InputString)=1--ODBC格式
    开始
    选择@Days=CAST(右(@InputString,2)作为int),
    @月份=强制转换(子字符串(@InputString,6,2)为int),
    @年份=强制转换(左(@InputString,4)为int)
    --注意:您需要为闰年添加一个条件
    如果(@Days<31和@Months IN(4,6,9,12))或(@Days<30和@Months=2)
    设置@DateValue=convert(日期,@InputString,120)
    终止
    返回@DateValue
    终止
    
    我可能会这样说:

    CREATE FUNCTION TryConvertToDate 
    (
        @InputString varchar(20)  
    )
    RETURNS Datetime
    BEGIN
        DECLARE @DateTime datetime = NULL
        SET @DateTime = 
           CASE 
               WHEN LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', @InputString)=1 THEN
                   CONVERT(DateTime, @InputString, 104) -- German
               WHEN LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', @InputString)=1 THEN
                   CONVERT(DateTime, @InputString, 120) -- ODBC
               ELSE
                   NULL -- unsuported format
           END
       RETURN @DateTime        
    END  
    
    注意:测试长度和使用确保只使用一般格式,因此您需要在try块中调用此函数,以防日期和月份颠倒,并导致转换错误。
    另一方面,将支持的格式添加到此函数非常简单-您所要做的就是添加一个
    when
    子句,该子句具有正确的
    patindex
    和长度以及正确的转换样式

    另一个选项是确保字符串可以实际转换为日期。
    这将使您的函数更复杂,因此更难编写,但更易于使用,因为它将使引发转换错误的可能性降至最低:

    CREATE FUNCTION TryConvertToDate 
    (
        @InputString varchar(20)  
    )
    RETURNS Datetime
    BEGIN
    
    
        DECLARE @DateValue date, @Days int, @Months int, @Years int
    
        IF LEN(@DateString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', @InputString)=1 -- German format
            BEGIN
                SELECT @Days = CAST(LEFT(@InputString, 2) As int),
                       @Months = CAST(SUBSTRING(@InputString, 4, 2) as int),
                       @Years = CAST(RIGHT(@InputString, 4) as int)
                -- NOTE: you will need to add a condition for leap years 
                IF (@Days < 31 AND @Months IN(4,6,9,12)) OR (@Days < 30 AND @Months = 2) 
                   SET @DateValue = convert(date, @InputString, 104)
            END
    
        IF LEN(@InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', @InputString)=1 -- ODBC format
            BEGIN
                SELECT @Days = CAST(RIGHT(@InputString, 2) As int),
                       @Months = CAST(SUBSTRING(@InputString, 6, 2) as int),
                       @Years = CAST(LEFT(@InputString, 4) as int)
                -- NOTE: you will need to add a condition for leap years 
                IF (@Days < 31 AND @Months IN(4,6,9,12)) OR (@Days < 30 AND @Months = 2)
                   SET @DateValue = convert(date, @InputString, 120)
            END
    
        RETURN @DateValue
    
    END
    
    创建函数TryConvertToDate
    (
    @InputString varchar(20)
    )
    返回日期时间
    开始
    声明@DateValue-date、@Days-int、@Months-int、@Years-int
    如果LEN(@DateString)=10和PATINDEX('[0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9][0-9]',@InputString)=1--德语格式
    开始
    选择@Days=CAST(左(@InputString,2)作为int),
    @月份=强制转换(子字符串(@InputString,4,2)为int),
    @年份=强制转换(右(@InputString,4)为int)
    --注意:您需要为闰年添加一个条件
    如果(@Days<31和@Months IN(4,6,9,12))或(@Days<30和@Months=2)
    设置@DateValue=convert(日期,@InputString,104)
    终止
    如果LEN(@InputString)=10和PATINDEX('[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]',@InputString)=1--ODBC格式
    开始
    选择@Days=CAST(右(@InputString,2)作为int),
    @月份=强制转换(子字符串(@InputString,6,2)为int),
    @年份=强制转换(左(@InputString,4)为int)
    --注意:您需要为闰年添加一个条件
    如果(@Days<31和@Months IN(4,6,9,12))或(@Days<30和@Months=2)
    设置@DateValue=convert(日期,@InputString,120)
    终止
    返回@DateValue
    终止
    
    这是我现在想到的功能:

    CREATE
    FUNCTION TryConvertStringAsDatetime (   @value VARCHAR(MAX),
                                            @format INT
                                        )
    RETURNS DATETIME
    AS
    /*
    Tries to convert a given VARCHAR value to DATETIME.
    Returns NULL if no value was specified or the value is not in the correct format.
    */
    BEGIN
    
        DECLARE @length INT = LEN(@value)
    
        IF @length IS NULL OR @length < 10 OR @length > 23
            RETURN NULL
    
        DECLARE @day VARCHAR(2),
                @month VARCHAR(2),
                @year VARCHAR(4),
                @time VARCHAR(9)
    
        IF @format = 104 --dd.mm.yyyy hh:mi:ss(24h)
        BEGIN
            SET @day = SUBSTRING(@value, 1, 2)
            SET @month = SUBSTRING(@value, 4, 2)
            SET @year = SUBSTRING(@value, 7, 4) 
        END
        ELSE IF @format IN (120, 121) --yyyy-mm-dd hh:mi:ss(24h)
        BEGIN
            SET @year = SUBSTRING(@value, 1, 4)
            SET @month = SUBSTRING(@value, 6, 2)
            SET @day = SUBSTRING(@value, 9, 2)              
        END
        ELSE
            RETURN NULL -- currently only german and ODBC supported
    
        IF @length > 11
            SET @time = SUBSTRING(@value, 12, @length - 11)
    
        SET @value = @year + '-' + @month + '-' + @day + ISNULL(' ' + @time, '')
    
        IF ISDATE(@value) = 1
            RETURN CONVERT(DATETIME, @value, 121)
    
        RETURN NULL
    
    END
    
    创建
    函数TryConvertStringAsDatetime(@value VARCHAR(MAX),
    @格式整型
    )
    返回日期时间
    像
    /*
    尝试将给定的VARCHAR值转换为DATETIME。
    如果未指定值或值的格式不正确,则返回NULL。
    */
    开始
    声明@length INT=LEN(@value)
    如果@length为NULL或@length<10或@length>23
    返回空值
    声明@day VARCHAR(2),
    @瓦查尔月(2),
    @第四年,
    @时间变量(9)
    如果@format=104--dd.mm.yyyy hh:mi:ss(24小时)
    开始
    设置@day=SUBSTR