답변:
대한 MSDN 문서 날짜는 사용을 권장 DATETIME2를 . 추천은 다음과 같습니다.
새로운 작업
time
에는date
,datetime2
및datetimeoffset
데이터 유형을 사용하십시오 . 이러한 유형은 SQL 표준과 일치합니다. 그들은 더 휴대용입니다.time
,datetime2
및datetimeoffset
초 이상 정밀도를 제공한다.datetimeoffset
전 세계적으로 배포 된 응용 프로그램에 대한 표준 시간대 지원을 제공합니다.
datetime2에는 더 큰 날짜 범위, 더 큰 기본 분수 정밀도 및 선택적 사용자 지정 정밀도가 있습니다. 또한 사용자가 지정한 정밀도에 따라 더 적은 스토리지를 사용할 수 있습니다.
DateTime2
Type 의 특정 비트 수준 표현 (또는 다른 SQL Server)에 의존하는 앱이 있습니까? 내가 묻는 이유는 아래 7/10/17 답변의 단점을 참조하십시오
DATETIME2
날짜 범위는 " DATETIME
0001/01/01 "에서 " 9999/12/31 "이며 유형은 1753-9999 년만 지원합니다.
또한 필요한 경우 DATETIME2
시간 측면에서 더 정확할 수 있습니다. DATETIME은 3 1/3 밀리 초로 제한되는 반면 DATETIME2
100ns까지 정확하게 측정 할 수 있습니다.
두 유형 모두 System.DateTime
.NET에 매핑됩니다 . 차이는 없습니다.
선택의 여지가 있다면 DATETIME2
가능할 때마다 사용하는 것이 좋습니다 . 나는 DATETIME
(후진 호환성을 제외하고) 사용 하면 어떤 이점도 얻지 못합니다 -날짜가 범위를 벗어난 번거 로움으로 어려움이 덜합니다.
플러스 : 날짜 만 필요하면 (시간 부분이없는 경우) DATE를 사용하십시오-날짜 DATETIME2
와 공간이 절약됩니다! :-) 같은 시간에만 사용 TIME
합니다. 이것이 바로 이러한 유형입니다.
Nullable<DateTime>
입니까?
datetime2 는 (이전 앱 호환성)을 제외한 대부분의 측면에서 승리합니다.
다음 사항에 유의하십시오
이미지 출처 : MCTS 자체 학습 교육 키트 (시험 70-432) : Microsoft® SQL Server® 2008-구현 및 유지 관리 3 장 : 표-> 1과 : 표 만들기-> 66 페이지
datetime2
(우승자)
datetime2
저장 공간을 적게 사용 datetime
하면서도 더 넓은 범위와 높은 정밀도를 제공하는 방법은 무엇입니까?
@marc_s 및 @Adam_Poward와 동의합니다 .DateTime2가 선호되는 방법입니다. 날짜 범위가 넓고 정밀도가 높으며 저장 공간이 같거나 적습니다 (정밀도에 따라 다름).
그러나 토론이 놓친 한 가지는 ...
@Marc_s states : Both types map to System.DateTime in .NET - no difference there
. 그러나 이것은 정확 하지 않습니다. 그 반대는 아닙니다. 날짜 범위 검색을 수행 할 때 중요합니다 (예 : "2010/5/5에서 수정 된 모든 레코드 찾기").
.NET의 버전은 Datetime
범위와 정밀도가 비슷합니다 DateTime2
. 닷넷을 매핑 할 때 Datetime
기존의 SQL까지 암시 반올림가 발생합니다 . 이전 SQL 은 3 밀리 초까지 정확합니다. 이것은 당신이 하루의 끝까지 갈 수있는 한 가깝다는 것을 의미합니다 . 더 높은 것은 다음 날로 올림됩니다.DateTime
DateTime
11:59:59.997
이 시도 :
declare @d1 datetime = '5/5/2010 23:59:59.999'
declare @d2 datetime2 = '5/5/2010 23:59:59.999'
declare @d3 datetime = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'
이 암시 적 반올림을 피하는 것이 DateTime2로 이동해야하는 중요한 이유입니다. 날짜의 암시 적 반올림은 분명히 혼란을 야기합니다
20100505
로 전환 한 이유는 무엇 5/5/2010
입니까? 전자의 형식은 SQL Server의 모든 지역에서 작동합니다. 후자는 끊어 질 것입니다 : SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')
죄송합니다 :2015-07-01 00:00:00.000
거의 모든 답변과 의견은 찬성에 대해 무겁고 단점을 밝혔습니다. 지금까지 모든 장단점에 대한 요약과 함께 한 번만 언급하거나 전혀 언급하지 않은 몇 가지 중요한 단점 (아래 2 번)이 있습니다.
1.1. 더 많은 ISO 호환 (ISO 8601) (실제로 이것이 어떻게 작동하는지 모르겠지만).
1.2. 더 많은 범위 (1/1/0001 ~ 12/31/9999 vs 1 / 1 / 1753-12 / 31 / 9999) (1753 이전의 모든 추가 범위는 예를 들어, 역사, 천문학, 지질학 등의 앱에서).
1.3. .NET의 DateTime
Type 범위와 정확히 일치합니다 (아래의 Con # 2.1을 제외하고 값이 대상 유형의 범위와 정밀도 내에 있으면 오류 / 반올림이 발생하는 경우 특별한 코딩없이 변환 할 수 있지만).
1.4. 더 정밀함 (100 나노초, 즉 0.000,000,1 초 대 3.33 밀리 초, 0.003,33 초) (예 : 공학 / 과학 응용 프로그램을 제외하고는 추가 정밀도가 사용되지 않을 수 있음).
1.5. Iman Abidi가 주장한 것처럼 (1 millisec에서와 같지 않고 (3.33 millisec에서와 같이) 비슷한 것으로 구성하면 DateTime
더 적은 공간 (7 대 8 바이트)을 사용하지만 물론, 당신은 정밀 이익은 아마 (필요하지 않은 이익이지만 가장 많이 선전 된 두 가지 범위 중 하나 일 것입니다).
2.1. 매개 변수를 .NET SqlCommand
에 System.Data.SqlDbType.DateTime2
전달할 DateTime
때는 기본값이이므로 SQL Server 의 범위 및 / 또는 정밀도를 벗어난 값을 전달할 수 있는지 여부를 지정해야합니다 System.Data.SqlDbType.DateTime
.
2.2. 숫자 값과 연산자를 사용하여 SQL Server 표현식에서 다음을 수행하기 위해 암시 적 / 쉽게 부동 소수점 숫자 (최소 날짜-시간 이후의 일 수) 값으로 변환 할 수 없습니다.
2.2.1. 일 또는 부분 일을 더하거나 뺍니다. 참고 : DateAdd
날짜-시간의 일부가 아닌 여러 항목을 고려해야 할 때는 기능을 해결 방법으로 사용 하는 것이 쉽지 않습니다.
2.2.2. "연령"계산을 위해 두 날짜-시간의 차이를 고려하십시오. 참고 : 대부분의 사람들이 예상 한대로 DateDiff
계산하지 않기 때문에 SQL Server의 함수를 대신 사용할 수는 없습니다 age
. 두 날짜 시간이 작은 경우에도 지정된 단위의 달력 / 시계 날짜-시간 경계를 넘을 경우 그 단위, 예를 들어 0 대 그 장치의 하나로서 차이를 리턴 거 상기 DateDiff
에서는 Day
'만 1 밀리 초 간격 해당 날짜 시간 인 경우 1 대 0 (일)을 반환 두 날짜 시간 S의 다른 날짜에 (예 : "1999-12-31 23 : 59 : 59.9999999"및 "2000-01-01 00 : 00 : 00.0000000"). 달력 날짜를 넘지 않도록 이동 한 경우 동일한 1 밀리 초 차이 날짜-시간 Day
은 0 (일)의 "DateDiff"를 반환합니다 .
2.2.3. 테이크 Avg
단순히 다시 제 다음 "플로트"로 변환하여 (집계 쿼리에서) 날짜 시간을 DateTime
.
참고 : DateTime2
숫자 로 변환하려면 값이 1970 년보다 작지 않다고 가정하는 다음 수식과 같은 작업을 수행해야합니다 (즉, 추가 범위와 추가 217 년을 모두 잃고 있음을 의미 함). 숫자 오버플로 문제가 발생할 수 있으므로 추가 범위를 허용하도록 수식을 간단히 조정할 수 없습니다.
25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0
– 출처 :“ https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html “
물론, 당신은 또한 수 Cast
에 DateTime
첫번째 (필요한 다시 다시하는 경우 DateTime2
),하지만 당신은 정밀도와 범위 (이전의 모든 년 1753) 혜택을 잃게 DateTime2
대 DateTime
prolly 2의 가장 큰 또한 동시에 prolly 있습니다 덧셈 / 뺄셈 / "나이"(vs. DateDiff
) / Avg
calcs 이익을 위해 암시 적 / 쉬운 부동 소수점 숫자 (일 수) 로의 변환을 잃을 때 왜 그것을 사용 하는가? 내 경험에.
Btw, Avg
날짜 시간은 중요한 유스 케이스입니다 ( 적어도 있어야 합니다). a) 날짜-시간 (공통 기본 날짜-시간 이후)을 사용하여 지속 시간을 나타내는 데 사용되는 평균 지속 시간을 얻는 데 사용 (공통 관행), b) 평균 날짜- time은 행 범위 / 그룹의 날짜-시간 열에 있습니다. c) 컬럼에서 유효하지 않거나 더 이상 유효하지 않거나 더 이상 사용되지 않아야하는 값을 모니터 / 문제 해결하기위한 표준 임시 쿼리 (또는 최소한 표준 이어야 함) 및 (사용 가능한 경우) Min
, Avg
및 Max
일시 타임 스탬프는 그 값과 관련된.
DateTime
은 SQL Server 쿼리 및 문에 대한 영향과 관련이 있습니다.
DateTime2
이미 언급 한 (오버플로 가능성이 높기 때문에) 특정 날짜 유형에서는 안전하지 않습니다. 레. "대부분의 날짜 유형에서는 작동하지 않습니다.": 하나만 사용하면되고 대부분의 앱에서 대부분의 날짜는 전체 수명 시간 동안 다른 날짜 유형으로 변환 할 필요가 없습니다. , DateTime2
하는 DateTime
그 모든 여분 만 프로그램뿐만 아니라 임시 연구 쿼리가 아닌 산술 친화적 인 날짜 형식을 사용하지 코딩 가치가 없어, 점을 감안 (P 예를 들면 "날짜 산술"해야 할 일)..
다음은 smalldatetime, datetime, datetime2 (0) 및 datetime2 (7)의 스토리지 크기 (바이트)와 정밀도의 차이를 보여주는 예입니다.
DECLARE @temp TABLE (
sdt smalldatetime,
dt datetime,
dt20 datetime2(0),
dt27 datetime2(7)
)
INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()
SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
dt,DATALENGTH(dt) as dt_bytes,
dt20,DATALENGTH(dt20) as dt20_bytes,
dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp
어떤 반환
sdt sdt_bytes dt dt_bytes dt20 dt20_bytes dt27 dt27_bytes
2015-09-11 11:26:00 4 2015-09-11 11:25:42.417 8 2015-09-11 11:25:42 6 2015-09-11 11:25:42.4170000 8
따라서 밀리 초가 아닌 초까지 정보를 저장하려면 datetime 또는 datetime2 (7) 대신 datetime2 (0)을 사용하면 각각 2 바이트를 절약 할 수 있습니다.
오래된 질문 ... 그러나 여기에 누군가가 아직 언급하지 않은 것을 추가하고 싶습니다 ... (참고 : 이것은 내 자신의 관찰이므로 참조를 요구하지 마십시오)
필터 기준에 사용하면 Datetime2가 더 빠릅니다.
TLDR :
SQL 2016에서는 최대 시간까지 정확한 시간을 저장해야했기 때문에 10 만 개의 행과 날짜 시간 열 ENTRY_TIME이있는 테이블이있었습니다. 많은 조인과 하위 쿼리로 복잡한 쿼리를 실행하는 동안 where 절을 다음과 같이 사용했습니다.
WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'
처음에는 수백 개의 행이 있었을 때 쿼리에 문제가 없었지만 행 수가 증가하면 쿼리에이 오류가 발생하기 시작했습니다.
Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.
where 절을 제거하고 예기치 않게 쿼리가 1 초 안에 실행되었지만 이제 모든 날짜의 모든 행을 가져 왔습니다. where 절을 사용하여 내부 쿼리를 실행하면 85 초가 걸리고 where 절이 없으면 0.01 초가 걸렸습니다.
날짜 시간 필터링 성능 으로이 문제에 대해 많은 스레드를 발견했습니다.
쿼리를 조금 최적화했습니다. 그러나 실제 속도는 datetime 열을 datetime2로 변경하는 것입니다.
이제 이전에 시간 초과 된 동일한 쿼리가 1 초도 걸리지 않습니다.
건배
미국 이외의 설정을 사용하는 경우 날짜 문자열을 해석 datetime
하고 datetime2
다를 수 있습니다 DATEFORMAT
. 예 :
set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2
에 대해 2013-05-06
(예 : 5 월 6 일) datetime
및에 대해 2013-06-05
(예 : 6 월 5 일)을 반환 합니다 datetime2
. 그러나,와 dateformat
로 설정 mdy
, 모두 @d
와 @d2
반환 2013-06-05
.
datetime
동작은과 상충 보인다 MSDN 설명서 의 SET DATEFORMAT
: 어떤 상태 예를 들어 ISO 8601을위한 독립적 DATEFORMAT 설정의 해석, 일부 문자열 형식 . 분명히 사실이 아닙니다!
이것에 물릴 때까지, 나는 yyyy-mm-dd
언어 / 로케일 설정에 관계없이 항상 날짜가 올바르게 처리 될 것이라고 생각 했습니다.
SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;
대시로 다시 시도하십시오.
Select ValidUntil + 1
from Documents
위의 SQL은 DateTime2 필드에서 작동하지 않습니다. "오퍼랜드 타입 충돌 : datetime2는 int와 호환되지 않습니다."
다음 날에 1을 더하면 개발자가 몇 년 동안 데이트를해온 것입니다. 이제 Microsoft는이 간단한 기능을 처리 할 수없는 완전히 새로운 datetime2 필드를 갖습니다.
"이전 유형보다 더 새로운 유형을 사용합시다"라고 생각하지 않습니다!
datetime
과 datetime2
데이터 유형이 모두 SQL Server 2008의 도입 또한 얻을 Operand type clash: date is incompatible with int
으로부터 date
하루 도트 이후 주변왔다 유형입니다. 세 가지 데이터 유형은 모두 잘 작동 dateadd(dd, 1, ...)
합니다.