데이터베이스에서 날짜를 문자열로 반환하지 않는 이유는 무엇입니까?


41

일반적인 웹 응용 프로그램에서 날짜는 강력하게 형식화 된 데이터베이스 계층에서 검색됩니다 (예 : c.에서는 System.DateTime과 반대로 System.String).

날짜를 문자열로 표현해야하는 경우 (예 : 페이지에 표시) DateTime에서 문자열로의 변환은 프리젠 테이션 계층에서 수행됩니다.

왜 이런거야? DateTime을 데이터베이스 계층의 문자열로 변환하는 것이 왜 나쁜가요?

또한 참조 채팅에서 뜨거운 논쟁 , 그리고 이 모든 시작 원래의 질문에 .


73
이 질문을하겠습니다. 모든 단일 유형을 문자열로 변환 하시겠습니까? Date가 다른 점은 무엇입니까?
gardenhead


8
글쎄, 다른 사람이 틀렸고 다른 모든 사람이 옳다는 것은 명백한 것 같습니다. 실제로 질문이 아닙니다
gardenhead

7
때로는 데이터베이스 외부에서 날짜 계산을해야합니다. 모든 것이 문자열이면 상당히 어려워집니다.
Eric King

14
또 다른 문제-어떤 종류 의 문자열이 필요합니까? 날짜 시간을 문자열로 나타내는 많은 방법이 있습니다. 에포크 이후 초 수로 표시되는 현재 시간 만 문자열로 반환 한 데이터베이스가있는 경우 (예 : 현재 시간은 "1474496980") 어떻게됩니까? 유용할까요? 그런 데이터베이스를 사용 하시겠습니까?
riwalk

답변:


168

날짜, 날짜 시간 및 기타 유형이 지정된 객체는 일반적으로 다른 유형으로 작성해야 할 때까지 (특히 해당 유형이 사람이 읽을 수있는 형식 일 때 , 특히 손실 / 단방향 변환

왜? 이 유형은 적절한 동등성 테스트, 덧셈 및 뺄셈, 비교 (보다 큼), 시간대 및 로케일 기능 (특히 시간 관련 사항에 특히 중요)과 같은 편리한 내장 기능을 많이 제공한다고 가정하기 때문에, 등. 미국인과 "월요일 (월, 일)"형식뿐만 아니라 일반적인 영국식 "월요일"또는 ISO 표준 "년-월-일"을 지원하려는 경우? 문자열이고 변경해야 할 경우 날짜로 다시 구문 분석하면 어떻게해야합니까? 어쨌든 고마워요. 많은 악과 끔찍한 벌레가 그런 식으로 있습니다.

보다 구체적으로, 나중에 계층 계층 구조를 언급했는데, 나중에 계층 계층 구조를 사용합니다. 실제로 날짜를 문자열이 아닌 날짜로 전달해야하는 또 다른 큰 이유는 날짜를 어떤 유형의 문자열 형식으로 입력해야합니까? 영어, 중국어, 초 / 밀리 초, 전체 월 이름 또는 숫자가 있거나없는 날짜 필드에서 나중에 정렬 하시겠습니까 (문자열 정렬시 올바르게 작동하려면 특정 문자열 형식이 필요함)? 이것은 모두 사용자가 데이터를 어떻게보아야하는지에 대한 프리젠 테이션의 문제입니다. 그리고 그 로직을 다른 곳에 배치하면 우선 계층 구조를 갖는 이점이 제한됩니다. 데이터베이스는 향후 날짜를보고자하는 방식을 알거나 신경 쓸 필요가 없습니다.

마지막으로, 시간을 염려하는 거의 모든 복잡한 응용 프로그램 (계층 식 아키텍처)은 시간, 날짜를 여러 가지 다양한 방식으로, 종종 모든 다른 수준의 아키텍처에서 사용해야합니다. 시간과 날짜와 관련된 유형이 지정된 객체는 정말 좋은 이유로 존재합니다. 시간 자체, 특히 사람 달력 시스템은 이상하고 어렵습니다. 궁극적으로 시간과 날짜는 정수와 부동 소수점이 문자열이 아니기 때문에 문자열이 아니며, 실제로 문자 배열이 아니라고 가정하면 삶을 더 어렵게 만듭니다.


26
별이없는 단어를 사용하기위한 +1. 귀하의 강력한 주장과 포괄적 인 설명에 동의하지만, 로그인하여 투표해야합니다.
Adrian Larson

1
과거에 정의 된 시간 이후 날짜 시간을 초 단위로 나타내는 것도 다른 달력에서 강력합니다. 예를 들어 이슬람과 중국 달력은 Greogrian 월, 연도 등을 사용하지 않습니다. 데이터베이스 수준에서 이것을 나쁜 습관으로 취급하는 것을 고려합니다.
rexkogitans

날짜는 종종 "X 일 전"으로 표시됩니다. 다시 원래 값으로 파싱하십시오.
Agent_L

5
DST 변경 (및 기타 유사한) 문제도 잊지 마십시오. 것 "2016년 11월 6일 오전 1시 30분 26초는" 이 날짜와 시간이 일어난 것을 처음 또는 두 번째가 될? UTC DateTime은 최소한 고유하며 항상 해당 시간의 로컬 표현으로 변환 할 수 있습니다. 다른 방법으로 되돌아가는 것이 항상 가능한 것은 아닙니다.
J ...

3
Why? Because it is assumed that the type provides you with lots of handy built in functionality제 생각에는 이것은 단지 이차적입니다. 진짜 이유는 형식 이 무엇인지 알려줍니다 . 날짜는 문자열 이 아니며 사람이 읽을 수있는 문자열로 쉽게 변환됩니다.
Doval

53

웹 서버를 사용하여 데이터 시간을 문자열로 변환하려고합니다. 나는 웹 서버가 아니라 데이터베이스 서버에서 그것을하고 있다고 말하고있다. 왜 그것이 더 낫다고 생각합니까? - MT 헤드

유형을 알고 싶습니다.

데이터베이스가 문자열, 일부 정수 또는 바이트로 정보를 저장하는지 여부는 실제로 중요하지 않습니다. 결국 항상 바이트입니다. 데이터베이스에서 필요한 것보다 더 많은 공간을 차지하는 문자열은 귀찮게하지 않습니다. 나를 귀찮게하는 날짜는 다음과 같습니다.

2016 년 11 월 10 일

그리고 그것이 11 번째 달인지 10 번째 달인지 모릅니다.

그러나 그것은 당신이 말하는 것으로 확인되었습니다. 반드시 검증 프로세스를 거쳐야합니다. 날짜가 완벽합니다. 그러나 여기에 나는 이것을 유지하고 있으며 날짜는 문자열이라는 것을 알고 있습니다. 나는 이것이 어떤 날짜인지 말할 수조차 없다.

"우리 주님의 이천 육십 년에 11 월 10 일."

문자열입니다. 프레젠테이션 중 하나가 해당 형식으로 필요합니다. 데이터베이스가 모든 날짜를 문자열로 변환한다고 말했습니까? 그것으로 재미있게 보내십시오.

데이터베이스의 임무는 데이터가없는 데이터를 저장하는 것입니다. 물론, 당신은 그것을 문자열로 할 수 있지만 다른 형식으로 제시하는 것이 유용하도록 파싱해야합니다. DB가 제공하는 모든 유형에 대해 표준 구문 분석 된 형식으로 저장하면 프리젠 테이션 결정을하지 않고도 프리젠 테이션 준비가 가능해집니다. DB가 해당 유형을 문자열 또는 정수 또는 바이트로 백업하는 경우 실제로 중요하지 않습니다. 그것이 무엇을하고 있는지 아는 한.

그러나 DB에 알리지 않으면 날짜를 처리하고 날짜를 문자열로 저장하여 다른 프레젠테이션보다 프레젠테이션을 조기에 제시하고 선호합니다. 그러면 다른 모든 발표자가 변환하기 전에 구문 분석합니다. 아니요, 데이터베이스는 프레젠테이션 계층의 일부가 아닙니다. 요구하지 마십시오.

마찬가지로 프레젠테이션 계층은 데이터베이스의 일부가 아니므로 보고서를 데이터베이스 세부 정보에 연결하는 것이 현명하지 않습니다. 유형에 대해 작동하는 것이 훨씬 강력합니다.


이 답변은 스토리지 를 문자열로 처리합니다. 그러나 기본 날짜 유형으로 날짜를 저장하는 일반적인 패턴을 다루지 않지만 CONVERT (T-SQL)와 같은 함수를 사용하여 SQL 쿼리에서 문자열로 형식화 하거나 DBMS가 일반적으로 날짜를 직렬화하지 않습니다. 쿼리에 관계없이 구성 가능한 형식의 문자열로 예를 들면 다음과 같습니다. postgresql.org/docs/9.5/static/…
dcorking

보고서입니다. 저장 후 발생합니다. 내 생년월일을 내 나이로 바꾸는 것과 같습니다.
candied_orange

2
OP의 주제는 " 데이터베이스 계층에서 날짜를 검색 하는 방법"이므로 OP의 주제를 확장하도록 권장하고 싶었습니다 . 보고서는 데이터베이스에서 형식화 된 현지화 된 날짜 문자열을 쿼리하는 잘 알려진 패턴이지만 더 이상 사용되지 않는 패턴이 있습니다. OP가 이러한 지원 중단 주장을 듣고 싶다고 생각합니다. 내가 할 줄 알아
dcorking

@dcorking 메모 업데이트.
candied_orange

+1 밀에 물을 더 추가 : 절대 순간이 가장 중요한 여러 시간대에 걸쳐 설치된베이스에 시스템을 만들고 문자열 <-> 타임 스탬프 변환이 얼마나 잘 수행되는지 확인하십시오. 최악의 경우, 사람들이 자신의 플러그인을 생성하고 문자열로 타임 스탬프를 줄 수있는 확장 점을 만드십시오.
Newtopian

19

장소

프리젠 테이션 목적으로 날짜를 문자열로 변환하려면 사용자 기본 설정을 알아야합니다. 일반적으로 정확한 날짜는 다른 로케일의 사용자에 대해 다르게 표시되어야하기 때문입니다. 응용 프로그램에서 단일 로캘을 사용하더라도 데이터베이스 서버 대신 응용 프로그램 의 로캘을 올바른 동작으로 사용해야 합니다. 현재 일치하는 경우에도 일치하지 않을 수 있습니다.

범용 날짜 데이터 유형에서 로케일 특정 문자열로의 변환은 프리젠 테이션 계층에서 수행되어야합니다. 변환이 수행 방법 을 알고있는 계층이기 때문 입니다.


3
로케일 불일치의 실제 사례를 보려면 미국 메인 사용자를위한 앱을 작성하고 아마존 서해안 서버 팜에서 호스팅한다고 상상해보십시오. ;) 이것은 실제로 상황이 아닙니다.
jpmc26

@ jpmc26 차이점을 이해하지 못합니다. 메인은 다른 미국과 ​​다른 날짜 형식을 사용합니까?
Pete Kirkham

2
@PeteKirkham Maine과 미국 서해안은 3 시간 간격의 시간대를 사용합니다.
jpmc26

1
또는 또 다른 실제 시나리오 : 로케일 (및 약간 다른 형식화 ​​규칙)을 가진 4 개 언어 (독일어, 프랑스어, 이탈리아어, 영어)로 클라이언트를 서비스해야하는 스위스에서 서버를 실행한다고 상상해보십시오 . 이러한 상황에서 서버에 적합한 로케일을 선택하십시오.
Voo

1
@ jpmc26 시간대와 로케일은 동일하지 않습니다. 예를 들어, 글래스고 스코틀랜드, 미국 애틀랜타 및 푸네 인도에 지사가 있습니다. 이 사무실의 컨설턴트는 차례로 전 세계의 모니터 사이트 (캠퍼스, 병원, 호텔 등)를 모니터합니다. 응용 프로그램 데이터베이스는 UTC로 작동하지만 모니터링중인 사이트의 현지 시간으로 시간을 표시합니다. 미국 컨설턴트는 날짜가 MM / DD / YYYY로 현지화되었지만 영국 및 인도 로케일은 DD / MM / YYYY입니다. 이는 사이트 또는 사용자의 시간대가 아닌 로케일에 따라 다릅니다.
Pete Kirkham

9

이것은 응용 프로그램 계층에 도달하자마자 유형을 문자열로 맹목적으로 변환 하지 않으려는 것과 같은 이유로 바람직하지 않습니다 . 사용자에게 객체를 제시하기 전에 어떤 방식 으로든 해당 객체를 사용하고 싶을 가능성이 높습니다 (사용자에게도 제공하는 경우). 이 특정 예에서는 물체에 대해 날짜 계산을해야한다고 상상해보십시오. 표시하기 전에 객체를 문자열로 정확하게 변환하는 것의 단점은 없습니다.


4

유형은 이유 때문에 존재합니다. 만약 아무런 이점이 없다면, 우리는 그것들을 갖지 못하고 사용하지 않을 것이며 우리는 단지 "유형"을 가질 것입니다. 그들은 편리하고 안전과 효율성을 추가합니다. 다음은 문자열이 아닌 항상 기본 형식으로 유형을 유지해야하는 이유의 목록입니다 . 필자 DateTime는 대부분 예제로 사용 했지만 정수, 소수, 이진 등과 같은 모든 기본 유형에 동일한 원칙이 적용됩니다.


데이터 저장소

제약

구속 조건

거의 모든 데이터 저장소는 데이터에 대한 제약 조건을 지정할 수 있으며 여기에는 유형 제약 조건이 포함됩니다. DateTime인스턴스 지정의 주요 이점 중 하나는 저장된 데이터가 해당 유형으로 제한된다는 것입니다. 상점에 데이터가 삽입 된 방식에 관계없이 날짜 시간 이외의 다른 것은 입력 할 수 없습니다. 후자는 상점과 직접 상호 작용하는 여러 프로세스가있는 더 큰 시스템에 중요합니다. 또한 2 월 30 일과 같이 잘못된 날짜를 추가하는 것도 포함됩니다 (2 월은 윤년에는 29 일, 비 윤년에는 28 일만있을 수 있음).

검증 제약

삽입 된 날짜가 현재 날짜를 초과하지 않거나 시작 날짜가 종료 날짜 이전에 발생하는지 확인하는 것과 같이 데이터 저장소에서 구현할 수있는 유효성 검사 제약 조건도 있습니다.

운영

대부분의 데이터 저장도 같은 작업 / 기능을 내장 한 DateAdd또는 DatePartMS SQL 서버한다. 이를 통해 데이터가 아직 상점에있는 동안 (아직 애플리케이션으로 검색되지 않은) 특정 데이터 필터링 또는 선택을 시작할 수 있습니다.

보편적으로 수용되는 형식

기본 유형을 사용하면 상점과 상호 작용하는 다른 개발자 또는 시스템에 해당 기본 유형이 저장되는 방법에 대한 세부 사항을 알 필요가 없습니다. 해당 유형이 문자열로 저장된 경우에는 해당되지 않으며, 모든 사람이 해당 DateTime문자열 표현 의 형식을 이해하도록해야합니다 . 이 시스템은 데이터 원본의 로캘, 지역 및 문화권에 걸친 데이터, 응용 프로그램의 실제 위치 및 해당 데이터와 상호 작용하는 최종 사용자 / 시스템의 특성을 처리 할 때 취약합니다. 예 : 한 국가의 날짜 형식은 미국과 같이 MM / dd / yyyy 일 수 있지만 다른 국가에서는 dd / MM / yyyy 일 수 있으며 차이가 거의 불가능하다는 것을 감지합니다.

속도

검색 속도, 유효성 검사 속도, 작업 속도 및 스토리지 효율성도 모두 중요한 요소입니다. 검색 속도의 예 : 데이터 저장소는 열에 대한 인덱스를 허용하며 이러한 인덱스는 일반적으로 형식이 기본 형식으로 저장된 경우 더 효율적으로 사용될 수 있습니다.

신청

데이터 접근

개발자가 스토리지 형식에 대해 추측 할 필요가 없으므로 기본 유형 시스템을 사용하여 상점에 대한 쿼리 실행이 더 간단 해집니다. 거의 모든 데이터 저장소 응용 프로그램 공급자 ( 예 : ado.net )는 전달 된 기본 형식을 기반으로 적절한 매개 변수화 된 쿼리를 만드는 메커니즘을 제공합니다. 다음은 SQL Server 저장소에 대해 ado.net 쿼리에 날짜 부분을 추가하는 예입니다. 문자열과 동일한 작업을 수행하는 것은 매우 번거롭고 깨지기 쉬운 / 오류가 발생하기 쉽습니다.

command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});

운영

코드의 기본 형식은 .net 형식과 같은 표준 작업을 제공합니다 System.Date. 연산은 일반적으로 날짜를 추가하거나 날짜 간의 차이를 찾는 등 수학적 특성을 가지고 있습니다. 다시 말하지만 문자열 유형에서는 쉽게 수행 할 수 없습니다.

프리젠 테이션 레이어

장소

프리미티브 유형이 최종적으로 프리젠 테이션 레이어에서 문자열로 변환 될 때 ( 프로그램 스택의 올바른 위치 ) 프로그래머는 현재 상황에 따라 올바르게 표시 할 수있는 다양한 옵션을 갖습니다. 이 컨텍스트는 일반적으로 데이터의 실제 의미와 사용자의 로캘로 구성됩니다.

실시 예 1

날짜 / 시간 인스턴스는 사용자의 로캘을 기반으로 자동 서식을 지정할 수 있습니다.

DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
실시 예 2

소수 인스턴스는 금액 (통화)을 나타낼 수 있으며 사용자의 로케일은 선호도에 따라 금액을 표시해야합니다. C # 응용 프로그램은 다음을 사용하여 값을 표시 할 수 있습니다.

amount.ToString("C", CultureInfo.GetCultureInfo(userContext.Culture))

다른 문화권에서는 숫자가 다르게 표시되므로 중요 할 수 있습니다. 미국 기간 (.)과 쉼표 (,)는 네덜란드에서와 같이 정확한 역의 의미를 갖습니다.

위치

이것은 DateTime인스턴스에 따라 매우 다릅니다 . 날짜 및 시간은 특정 시점에서의 발생을 나타내지 만 일반적으로 자신의 시간대에 따라 사용자에게 전달 / 제공되어야합니다. 예 : 미국 동부 표준 시간대의 사용자 는 DateTime인스턴스를 2016-09-21T23:38:21.399Z표시 할 수 있습니다 9/21/2016 5:21 PM. 이를 수행하는 방법에는 여러 가지가 있지만 날짜 시간 인스턴스가 메모리에 문자열 유형으로 또는 데이터 저장소에 문자열 유형으로 유지되는 경우 불가능 해집니다.


일반 규칙

프리미티브 유형을 문자열 표현으로 변환 할 때 적용되는 일반적인 2 가지 규칙은 다음과 같습니다.

  • 입력을 수락 할 때 프로그램 스택에서 가능한 빨리 (일반적으로 프리젠 테이션 레이어에서) 해당 입력을 올바른 기본 유형으로 변환하십시오.
  • 표시 할 데이터를 검색 할 때 프로그램 스택에서 가능한 한 늦게 (대개 프리젠 테이션 계층에서) 해당 데이터를 문자열 표현으로 변환하십시오.

0

날짜에 모호하지 않은 형식을 사용하는 한 실제로 서비스에 항상 문제가 없습니다. 분명히, 나는 날짜가 분명 할뿐만 아니라 (예 : MM / DD vs. DD / MM) 시간대를 의미합니다. 따라서 날짜를 텍스트로 표현하려는 경우 ISO 형식을 사용하십시오. . UTC 기반 시간 문자열을 선호합니다.

장점 :

  • 표준 기반 날짜 / 시간 문자열은 이식 가능하고 이해하기 쉽습니다.
  • DB의 날짜에는 종종 시간 구성 요소가 포함됩니다. 이것이 데이터에 의미가 없다면 실제로는 단순화 할 수 있습니다.

단점 :

  • 데이터 크기. DB에서 날짜의 내부 형식은 일반적으로 해당 날짜의 문자열 렌더링보다 훨씬 적은 공간을 사용합니다.
  • 일반적으로 클라이언트에서 실제 날짜 또는 시간 구조로 가져 와서 구문 분석에 추가 시간이 필요할 수 있습니다.

누군가이 작업을 원한다고 말하면 "왜?"라고 물을 것입니다. 그다지 지적 할 것이 없기 때문입니다. 누군가가 날짜를 문자열로 반환하려는 이유가 바로 날짜를 표시하기 때문에 DB의 문자열을 사용하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.