【问题标题】:How to insert DDMMYYYY value in DATE datatype column如何在 DATE 数据类型列中插入 DDMMYYYY 值
【发布时间】:2021-09-14 19:53:51
【问题描述】:

我创建了具有以下结构的表。

CREATE TABLE TEMP_CUSTOMERS 
(
    CUSTOMER_NAME VARCHAR(255) NOT NULL,
    CUSTOMER_ID VARCHAR(18) NOT NULL,
    CUSTOMER_OPEN_DATE DATE NOT NULL,
    LAST_CUNSULTED_DATE DATE,
    VACCINATION_TYPE CHAR(5),
    DOCTOR_CONSULTED CHAR(5),
    STATE CHAR(5),
    COUNTRY CHAR(5),
    POST_CODE INT,
    DATE_OF_BIRTH DATE,
    ACTIVE_CUSTOMER CHAR(1)
)

我想插入以下值

INSERT INTO TEMP_CUSTOMERS (CUSTOMER_NAME, CUSTOMER_ID,
                            CUSTOMER_OPEN_DATE, LAST_CUNSULTED_DATE,
                            VACCINATION_TYPE, DOCTOR_CONSULTED,
                            STATE, COUNTRY, DATE_OF_BIRTH, ACTIVE_CUSTOMER) 
VALUES ('ALEX', '123457', '20101012', '20121013', 'MVD', 'PAUL', 'SA', 'USA', '06031987', 'A'),
       ('JOHN', '123458', '20101012', '20121013', 'MVD', NULL, 'TN', 'IND', '06031987', 'A'),
       ('MATHEW', '123459', '20101012', '20121013', 'MVD', NULL, 'WAS', 'PHIL', '06031987', 'A'),
       ('MATT', '12345', '20101012', '20121013', 'MVD', NULL, 'BOS', 'NYC', '06031987', 'A'),
       ('JACOB', '1256', '20101012', '20121013', 'MVD', NULL, 'VIC', 'AU', '6031987', 'A')

但是在将 06031987 值插入 DATE_OF_BIRTH 列时出现错误。我尝试了转换、投射、设置日期格式……但没有成功。

请帮帮我。

【问题讨论】:

  • 不要使用那种格式,使用yyyyMMdd,这是明确的。
  • 为了呼应拉努,我什至不知道那是 6 月 3 日还是 3 月 6 日,除了你的问题标题是 ddmmyyyy。这不是一种有效的格式 - 修复源以使用正确的、明确的、非区域格式。
  • 您的其他日期显然使用了不同的格式。甚至可能是正确的格式。那么,到底为什么你还试图接受不同的(无意义的)dob 格式?无论提供或预处理此数据的任何内容都需要修复。
  • 我也希望6031987 是一个与您的问题无关的错字。如果你被垃圾卡住了,但甚至不能依赖源来提供一致垃圾,我认为你不能围绕这个编写可靠的代码。
  • 由于您在 DATE_OF_BIRTH 列中遇到了一些垃圾,如果它是一致的垃圾并且始终以 DDMMYYYY 格式出现,那么请查看 Venkataraman R 发布的解决方案(带有 DATEFROMPARTS 的解决方案。我必须不过告诉你,你发布的生日都是美国人的,这里的很多人都使用 MMDDYYYY 格式。你真的需要确定。找一个 DD 或 MM 超过 12 岁的人。实际上会将该列定义为 DD 列。

标签: sql sql-server tsql


【解决方案1】:

对于日期文字,您应该将年份放在首位,然后是月份,然后是日期,总是。所以06031987 应该是19870306没有例外。 1987-03-06 也是允许的,但这仍然使用年,然后是月,然后是日。对于仅日期值(没有时间部分),未分隔的版本是 Sql Server 的更好选择。

其他任何东西仍然是一个字符串,而不是一个日期。如果您需要日期,则必须手动转换它。这是可能的,但速度较慢,并且仅限于此处文档中显示的格式:

https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql

请注意,这些格式中没有一个与您想要的DDMMYYYY 匹配。你能得到的最接近的是DD/MM/YYYY,这不是一回事。这意味着您需要将字符串组件解析为与其中一种格式兼容的新值。

最后,为了完整起见,我需要提及FORMAT() 函数。此函数将允许您使用DDMMYYYY 格式,但它仅用于将日期转换为字符串,反之亦然。它不会帮助你走向相反的方向。

【讨论】:

  • 作为一个侧边栏,您应该认真避免在 T-SQL 中使用 FORMAT() 函数。在大多数情况下,它甚至比字符串函数和 CONVERT 的一些奇特组合慢 43 倍。
【解决方案2】:

如果你不能改变源,你可以处理糟糕的格式,但它真的非常难看。这里有几种方法(至少有十几种方法可以执行字符串操作和应用样式编号以使 SQL Server 理解并将垃圾转换为您可以使用的东西):

DECLARE @BadFormat varchar(10) = '06031987';

-- if it's mmddyyyy? June 3rd. Switch to yyyymmdd and use style 112.
SELECT TRY_CONVERT(date, RIGHT(@BadFormat,4) + LEFT(@BadFormat,4), 112);

-- if it's ddmmyyyy? March 6th. Make it dd/mm/yyyy and use style 103.
SELECT TRY_CONVERT(date, STUFF(STUFF(@BadFormat, 5,0,'/'),3,0,'/'), 103);

但是,请,请,请尝试修复源以向您发送正确、明确、非区域性的格式。正如 Joel 所建议的,这只是 YYYYMMDDYYYYMMDDYYYY-MM-DD 似乎安全,但事实并非如此:

SET LANGUAGE Français;
SELECT CONVERT(datetime, '1987-06-13');

结果(不仅是法语,而且实际上是 SQL Server 支持的超过一半的语言):

消息 242,级别 16,状态 3
La conversion d'un type de données varchar en type de données datetime a créé une valeur hors limites。

有关更多背景信息,请参阅:

【讨论】:

    【解决方案3】:

    您可以使用DATEFROMPARTS 从文字生成日期值,如下所示:

    declare @datevalue CHAR(8) = '06031987'
    
    select DATEFROMPARTS(RIGHT(@datevalue,4),SUBSTRING(@datevalue,3,2),LEFT(@datevalue,2))
    

    1987-03-06

    【讨论】:

    • 不仅正确,而且是最快的方法之一。做得很好!
    • @JeffModen,感谢您的鼓励
    【解决方案4】:

    您最常将意大利语或西班牙语日期“06031987”转换为有效的 SQL 日期类型格式。默认是YYY-MM-DD,所以可以实现一个子串函数来分解这个值'06031987'

    SubString( @Date, 5, 4 ) + '-' + SubString( @Date, 3, 2 ) +'-' + SubString( @Date, 1, 2 )
    

    或者像这样创建一个用户函数。

    Create Function dbo.fnConvertDMYtoSQLDate ( @Date VarChar( 8 ) )
    Returns VarChar( 10 )
    As
     Begin
      Declare @dt VarChar( 10 )
      Set @dt = SubString( @Date, 5, 4 ) +
                '-' +
                SubString( @Date, 3, 2 ) +
                '-' +
                SubString( @Date, 1, 2 )            
      Return @Dt  
     End
    go
    

    然后这样称呼它。 Select dbo.fnConvertDMYtoSQLDate('06031987')。 在插入中,您可以这样使用它:

    INSERT INTO TEMP_CUSTOMERS (CUSTOMER_NAME, CUSTOMER_ID,
                                CUSTOMER_OPEN_DATE, LAST_CUNSULTED_DATE,
                                VACCINATION_TYPE, DOCTOR_CONSULTED,
                                STATE, COUNTRY, DATE_OF_BIRTH, ACTIVE_CUSTOMER)
     VALUES('ALEX', '123457', '20101012', '20121013', 'MVD', 'PAUL', 'SA', 'USA', dbo.fnConvertDMYtoSQLDate('06031987'), 'A')
    

    【讨论】:

      【解决方案5】:

      试试这个:

      DECLARE @DateString varchar(10) = '06031987';
      SELECT REPLACE(CONVERT(date,STUFF(STUFF(@DateString,3,0,'/'),6,0,'/')),'-', '')
      

      【讨论】:

      • 如果原始字符串的格式是 MMDDYYYY,那将是正确的。但是,如果你看这篇文章的标题,原来的字符串格式实际上是 DDMMYYYY。
      • 哦,好的。我的错。谢谢。
      猜你喜欢
      • 2021-04-04
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 1970-01-01
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      相关资源
      最近更新 更多