简体   繁体   English

如何在 SQL 服务器中将 nvarchar 日期从一列转换为另一列

[英]How to convert nvarchar to date from one column to another in SQL Server

I have a column called “Month Year Raw” that has multiple nvarchar type data like this: 202201 and I want to convert that to a column called “Month Year” that will be like “January 2022”.我有一个名为“Month Year Raw”的列,其中包含多个 nvarchar 类型的数据,如下所示:202201,我想将其转换为名为“Month Year”的列,类似于“January 2022”。

This is really bad news.这真是个坏消息。 You shouldn't be storing dates as strings at all, never mind multiple times (which is just redundant storage for no gain).根本不应该将日期存储为字符串,更不用说多次(这只是多余的存储而没有任何好处)。 Even nvarchar is bad;甚至nvarchar也不好; why would you ever need to use Unicode characters to represent yyyyMM ?为什么你需要使用 Unicode 个字符来表示yyyyMM I know 2020 was bad but you still can't use 4 poop emojis ( 03 ).我知道 2020 年很糟糕,但您仍然不能使用 4 个便便表情符号 ( 03 )。

Store a date as a proper date/time data type, then you get built-in validation, sargable queries, date math, etc. You can always derive these display formats where they belong, at display time.将日期存储为适当的日期/时间数据类型,然后您将获得内置验证、可搜索查询、日期数学等。您始终可以在显示时间派生出这些显示格式。

Plenty of other advice at Dating Responsibly .负责任地约会中还有很多其他建议。

Until you can fix this:直到你能解决这个问题:

UPDATE dbo.BadIdeas 
SET [Month Year] = CONCAT
  (
    DATENAME(MONTH, CONVERT(datetime, 
       [Month Year Raw] + '01', 112)),
    ' ', 
    YEAR(CONVERT(datetime, 
       [Month Year Raw] + '01', 112))
  );

If you're just wondering about the programmatic possibilities - "202201" would take the LEFT(4) chars for the year and RIGHT(2) chars for the month.如果您只是想知道编程的可能性 - “202201”将采用LEFT(4)字符作为年份, RIGHT(2)个字符作为月份。 Lets assume you were handed that non-atomic nvarchar string and just needed a one-time ad-hoc query.假设您收到了那个非原子 nvarchar 字符串,并且只需要一个一次性的临时查询。

You would not add a new column to the table, just select what's needed for output. There is a built-in SQL Server function called DATENAME() that convert numbers into month names.您不会向表中添加新列,只是 select 需要 output。有一个名为 DATENAME DATENAME()的内置 SQL 服务器 function 可将数字转换为月份名称。 Since the data is stored in nvarchar you need to convert to a compatible integer in order to use those functions so I'll use CAST() .由于数据存储在 nvarchar 中,您需要转换为兼容的 integer 才能使用这些函数,因此我将使用CAST()

DECLARE @variable nvarchar(100) = '202201'

SELECT DATENAME(MONTH, CAST(RIGHT(@variable, 2) as int)) + ' ' + LEFT(@variable, 4) AS [Answer]

Results in output: output 中的结果:

January 2022 2022 年 1 月


A few things I will point out:我要指出的几件事:

  1. nvarchar costs 2 bytes of storage per character plus 2 bytes for the variable overhead. nvarchar 每个字符占用 2 个字节的存储空间,外加 2 个字节的变量开销。 "202201" costs 14 bytes total. “202201”总共花费 14 个字节。 Alternatively, datetime only costs 8 bytes total storage.或者,datetime 仅花费 8 字节的总存储空间。
  2. The datetime datatype is the only datatype designed to work with SQL Server's built-in functions which is why you are being told to store dates in the correct datatype. datetime 数据类型是唯一设计用于 SQL 服务器内置函数的数据类型,这就是为什么您被告知以正确的数据类型存储日期。
  3. Combining month and year into the same custom string is a violation of 1NF since the data is not atomic.将月份和年份组合到同一个自定义字符串中违反了 1NF,因为数据不是原子的。 When you have non-atomic data you end up having to extract parts of string using LEFT() and RIGHT() , etc. If you need to use system functions you will have to transform the non-atomic data using CAST() .当您拥有非原子数据时,您最终不得不使用LEFT()RIGHT()等提取部分字符串。如果您需要使用系统函数,则必须使用CAST()转换非原子数据。

Example of using a datetime datatype instead:改为使用日期时间数据类型的示例:

DECLARE @variable2 datetime = '2022-01-01'
SELECT FORMAT (@variable2, 'MMMM yyyy')

Also results in:还导致:

January 2022 2022 年 1 月

Using the correct datatype results in shorter code, and does not require extracting or transformation of data.使用正确的数据类型可以缩短代码,并且不需要提取或转换数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM