datetime 형의 컬럼에 대한 정리 > db

본문 바로가기

db

datetime 형의 컬럼에 대한 정리

페이지 정보

작성자 서방님 댓글 0건 조회 21회 작성일 07-07-09 09:38

본문

datetime 형에 대해서 잘 모르는 분들이 의외로 많은듯 하여 또다시 갑작스레 정리...
/* ------------------------------------------------------------------------------ */
사례1 : em에서 데이터조회시 오전, 오후 라는 문구로 인한 착오
사례2 : 요일명(일, 월, 화, 수, 목, 금, 토) Display문제
사례3 : 날짜+시간 형태의 문자형 컬럼을 datetime형으로 변환
사례4 : 오늘자 자료 검색문제
사례5 : datetime 컬럼이 문자형이라는 잘못된 인식
사례6 : 사용자정의 함수에서 getdate()를 사용하고자 할때(더미테이블 또는 뷰를 사용)
사례7 : 근속일수 구하는 함수
사례8 : 특정기간중 특정요일의 수를 구하는 함수

추가 : ASP에서 NOW()함수의 사용으로 인한 문제
추가 : 해당월의 n주차 시작일 구하는 함수
추가 : 만나이 계산
추가 : 오라클의 to_date를 sql server에서 사용할경우
추가 : 한글 Windows, 한글 SQL 사용시 영문 날짜명칭이 필요할 경우
/* ------------------------------------------------------------------------------ */
사례1 : EM에서 데이터조회시 오전, 오후 라는 문구로 인한 착오

컬럼을 datetime형으로 만들구 em에서 보면 2003-01-03 오후 3:23:44 이런식으로
보여져서 실제 db에 저장된것이 오전, 오후 라는 문구가 같이 저장된것으로 잘못생각하는
초보자들이 있다.

em에서 데이터를 확인해보면 분명히 '2003-01-03 오후 3:23:44' 과 같이 표기되어 있다.
이것은 db에 저장된 값이 그러하다는것이 아니라 em이라는 툴에서 그렇게 보여지는것 뿐이다.
em은 ms에서 만든 툴이다. 간단히, vb나 asp등에서 format을 그렇게 주었다고 생각하면 더 쉬울듯.

그럼, 실제로 db에 어떻게 저장되어 있는지 확인해보자.

실질적으로 db에 저장될때는 date를 위해서 4byte, time을 위해서 4byte 이렇게해서
8byte의 저장공간을 차지하고, 숫자형으로 저장이 된다.

--drop table a
create table a(dt datetime)
insert into a values('2003-06-10 10:00:00.000')
insert into a values('2003-06-11 10:00:00.000')
insert into a values('2003-06-11 10:00:01.000')

select first from sysindexes where id=object_id('a')
select convert(int, 0x0f) --15

dbcc traceon(3604)
dbcc page(tempdb, 1, 15, 1)

Slot 0, Offset 0x60
-------------------
228A4060:  000c0010  00a4cb80  00009394

Slot 1, Offset 0x6f
-------------------
228A406F:  000c0010  00a4cb80  00009395

Slot 2, Offset 0x7e
-------------------
228A407E:  000c0010  00a4ccac  00009395

실제 물리적으로 저장된 형태를 보면 앞의 4byte는 그냥 넘어가구
그다음 4byte가 time 값 그다음 4byte가 date 값이다.

문자형으로 저장되는 것이 아니라 숫자형으로 저장이 되면 date 값과 time 값이
각각 4byte씩 분리되어서 저장이 된다.
(저장구조에 대해서 좀더 자세히 볼려면 심심풀이 5탄을 참고하세요. 바로밑 url참고)
http://sqler.pe.kr/web_board/view_list.asp?id=7858&read=479&pagec=&found=is&part=myboard4&ser=yes

그래서, datetime 형의 컬럼을 조회 할려면

select * from a where dt = '2003-06-10 오전 10:00:00.000'

이런식으로 조회를 하는것이 아니라

select * from a where dt = '2003-06-10 10:00:00.000'

이런식으로 조회를 해야한다.

/* ------------------------------------------------------------------------------ */
사례2 : 요일명(일, 월, 화, 수, 목, 금, 토) Display문제 : datename()함수 사용

declare @dt datetime
set @dt = getdate()
select case datepart(dw, @dt) when 1 then '일요일'
                              when 2 then '월요일'
                              when 3 then '화요일'
                              when 4 then '수요일'
                              when 5 then '목요일'
                              when 6 then '금요일'
                              when 7 then '토요일' end 요일

/* ------------------------------------------------------------------------------ */
사례3 : 날짜+시간 형태의 문자형 컬럼을 datetime형으로 변환

declare @dt varchar(20)
set @dt = '200306111210' --2003년 06월 11일 12시 10분
select convert(datetime, left(@dt,8)+' '+substring(@dt,9,2)+':'+substring(@dt,11,2))

-----------------------
2003-06-11 12:10:00.000

(1개 행 적용됨)

즉, 문자형으로 된것을 datetime형으로 변경할경우는
1. yyyy-mm-mm hh:mm:ss
2. yyyy/mm/dd hh:mm:ss
3. yyyymmdd hh:mm:ss

와 같은 형태로 변형해서 convert()함수나 cast()함수를 사용하여 형변환 하면 된다.
time부분의 시:분:초 사이에 구분자로 ':'이 와야하고 date와 time값 사이에 공란이 한칸와야한다.

또는 아래와 같이 함수를 하나 만들어두고서 사용하는것도 괜찮을것 같네요.

--drop function dbo.to_date
create function dbo.to_date(@str char(14))
returns datetime
as
begin
   return (convert(datetime, case when len(@str) = 8 then @str
                                  else left(@str,8)+' '+
                                       substring(@str,9,2)+':'+
                                       substring(@str,11,2)+':'+
                                       substring(@str,13,2) end))
end
go

--ex :

select dbo.to_date('20941111101010')
-----------------------
2094-11-11 10:10:10.000

(1개 행 적용됨)


반대의 경우라면

--drop function dbo.to_char
create function dbo.to_char(@dt datetime)
returns char(14)
as
begin
   return (replace(replace(replace(convert(varchar(20), @dt, 120),':','-'),'-',' '),' ',''))
end
go

--ex :
select dbo.to_char(getdate())

--------------
20040128105301

(1개 행 적용됨)

/* ------------------------------------------------------------------------------ */
사례4 : 오늘자 자료 검색문제

--drop table #a
create table #a (dt datetime)
insert into #a values ('2003-06-10 13:56:30.000')
insert into #a values ('2003-06-11 01:56:30.000')
insert into #a values ('2003-06-11 10:56:30.000')
insert into #a values ('2003-06-11 23:56:30.000')
insert into #a values ('2003-06-12 00:00:00.000')
insert into #a values ('2003-06-12 13:56:30.000')
go
create index idx on #a(dt)

이것을 하기 위해서 알아야할 사항

먼저 시간을 지정하지 않고 날짜값만을 나열하면 시간은 어떻게 셋팅될까 ?

select convert(datetime, '2003-06-11')

-----------------------
2003-06-11 00:00:00.000

(1개 행 적용됨)

즉, 일자만 나열하면 시간은 0으로 셋팅된다.

그 다음으로, 해당일의 max time 값은 23:59:59.997 이다.

확인해보자.
--drop table #t
create table #t(no char(3), dt datetime)
insert into #t values('996','2003-06-11 23:59:59.996')
insert into #t values('997','2003-06-11 23:59:59.997')
insert into #t values('998','2003-06-11 23:59:59.998')
insert into #t values('999','2003-06-11 23:59:59.999')
go
select * from #t

no   dt
---- -----------------------
996  2003-06-11 23:59:59.997
997  2003-06-11 23:59:59.997
998  2003-06-11 23:59:59.997
999  2003-06-12 00:00:00.000

(4개 행 적용됨)

sql-server에서 time은 3/1000 의 정밀도를 가진다. 즉, 3/1000초 단위로 반올림 처리된다.
996의 경우 반올림에 의해서 997로
997의 경우 반올림에 의해서 997로
998의 경우 반올림에 의해서 997로
999의 경우 반올림에 의해서 다음날 자정으로 db에 입력된다.

--위의 사항을 숙지했다면 이제 오늘자 자료를 보는 쿼리문을 작성해보자.
set statistics profile on --인덱스 활용여부를 확인하기 위해서 설정하구

방법1 : 부등호 연산
select * from #a where dt >= '2003-06-11' and dt < '2004-06-12'
  |--Index Seek(OBJECT:([tempdb].[dbo].[#a].[idx]),
     SEEK:([#a].[dt] >= '06 11 2003 12:00AM'
       AND [#a].[dt] < '06 12 2004 12:00AM') ORDERED FORWARD)

방법2 : between 사용시
select * from #a where dt between '2003-06-11' and '2004-06-11 23:59:59.997'
  |--Index Seek(OBJECT:([tempdb].[dbo].[#a].[idx]),
     SEEK:([#a].[dt] >= '06 11 2003 12:00AM'
       AND [#a].[dt] <= '06 11 2004 11:59PM') ORDERED FORWARD)

위에서 나열한 두가지 방법으로 쿼리해야지 index seek을 하지
그렇지 않고 아래와 같은 쿼리문을 작성한다면
인덱스가 있다고 하더라도 인덱스를 정상적으로 사용하지 못하게 된다.

나쁜방법1 : datetime 컬럼에다가 convert() 사용
select * from #a where convert(char(10), dt, 120) = '2003-06-11'
  |--Index Scan(OBJECT:([tempdb].[dbo].[#a].[idx]),  WHERE:(Convert([#a].[dt])='2003-06-11'))

나쁜방법2 : datetime 컬럼에다가 datepart() 사용
select * from #a where year(dt)=2003 and month(dt)=6 and day(dt)=11
  |--Index Scan(OBJECT:([tempdb].[dbo].[#a].[idx]),
     WHERE:((datepart(month, [#a].[dt])=6
         AND datepart(day, [#a].[dt])=11)
         AND datepart(year, [#a].[dt])=2003))

나쁜방법3 : datetime 컬럼에다가 year(), month(), day() 등의 함수사용
select * from #a where datepart(yy,dt)=2003 and datepart(mm,dt)=6 and datepart(dd,dt)=11
  |--Index Scan(OBJECT:([tempdb].[dbo].[#a].[idx]),
     WHERE:((datepart(month, [#a].[dt])=6
         AND datepart(day, [#a].[dt])=11)
         AND datepart(year, [#a].[dt])=2003))

결과를 보면 위의 3가지 모두 index seek이 아니라 index scan이다.
인덱스가 있다고 하더라도 제대로 사용하지 못하게 되는것이다.

/* ------------------------------------------------------------------------------ */
사례5 : datetime 컬럼이 문자형이라는 잘못된 인식

datetime 컬럼은 문자형이 아니라 숫자형이다.
즉, 변수를 이용한 검색시 변수의 형을 정확히 일치시켜주어야지 그냥 아무생각없이 사용한다면
자동형변환으로 인해서 index 를 제대로 활용하지 못하는 경우도 있다.

--있으면 지우고
drop table b
go
--테스트용 테이블 하나 만들고
create table b(dt1 datetime, dt2 char(8))
go
--역시나 테스트용 데이터 넣구
set nocount on
go
declare @i datetime
set @i = '2000-01-01'
while (@i <= '2003-12-31')
begin
insert into b values (@i, convert(varchar(8), @i, 112))
set @i = dateadd(dd, 1, @i)
end
go
set nocount off
go
--인덱스 만들구
create index idx on b (dt1)
create index idx2 on b (dt2)
go

--실행계획을 보기위해 설정
set statistics profile on
go

--1. datetime 컬럼에다가 문자를 비교하면 ?
declare @dt2 char(8)
set @dt2 = '20030505'
select * from b where dt1 = @dt2
  |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[b]))
       |--Index Seek(OBJECT:([tempdb].[dbo].[b].[idx]),
          SEEK:([b].[dt1]=Convert([@dt2])) ORDERED FORWARD)

문자형인 @dt2 변수를 숫자형인 dt1컬럼과 비교하기 위해서 자동형변환에 의해서
datetime형으로 변환하여 정상적으로 index seek 을 한다.

--2. 문자컬럼에다가 datetime을 비교하면 ?
declare @dt1 datetime
set @dt1 = '2003-05-05'
select * from b where dt2 = @dt1
  |--Table Scan(OBJECT:([tempdb].[dbo].[b]), WHERE:(Convert([b].[dt2])=[@dt1]))

이번에는 반대로 문자형으로 설정된 dt2컬럼과 dateime형으로 선언된 @dt1변수를
비교하기 위해서 문자형인 dt2컬럼을 datetime 형으로 형변환을 하여 검색을 할려고 한다.
즉, 일반적인 문자형과 숫자형의 경우와 동일한 현상이 발생하는 것이다.
(참고로, 문자형과 숫자형의 경우데 대해서 볼려면 심심풀이 1탄을 참고하세요. 바로밑 url참고)
http://sqler.pe.kr/web_board/view_list.asp?id=7696&read=187&pagec=2&found=is&part=myboard4&ser=yes

/* ------------------------------------------------------------------------------ */
사례6 : 사용자정의 함수에서 getdate()를 사용하고자 할때

--방법1. 더미테이블 사용

정상적인 방법으로는 안됩니다.
사용자정의 함수는 확정적함수만을 사용해서 만들어야 합니다.
getdate()는 대표적인 비확정적함수이므로 사용할수가 없습니다.
그래서 편법을 사용해서 처리해야합니다.

먼저 더미테이블 하나만들구
--drop table dumy
create table dumy(c1 int, c2 as getdate())
이때 첫번째 컬럼은 아무것이나 만들면 되지만 두번째 컬럼은 계산되열을 만드는것입니다.
c2컬럼을 계산된열로 하구서 그값을 getdate()라고 주었지요.

이제 이것을 이용해먹을려면 의미없는 레코드하나를 추가합니다.
insert into dumy(c1) values(1)

그러구나서
select c2 from dumy
를 하게되면 항상 getdate()값을 가져오게 됩니다.

이제, 만들고자 하는 사용자정의함수에서 위 select 문을 사용하면 정상적으로 만들어 집니다.

--샘플로 오늘부터 n일 뒤의 날짜를 구하는 함수를 만들어보면
--drop function dbo.test
create function dbo.test(@diff int)
   returns datetime
as
begin
   return (select convert(char(10), dateadd(dd, @diff, c2), 112) from dumy)
end
go

select dbo.test(10)

정상적으로 만들어지고 잘동작합니다.


--방법2. 뷰의 사용

출처 : http://www.sqlservercentral.com/
Columnist : Nagabhushanam Ponnapalli
Posted    : 2003/08/07

1. 먼저 뷰를 하나 만들고
--drop view v1
create view v1
as
   select getdate() systemdate
go


2. 위에서 만든 뷰를 udf에서 사용
--drop function dbo.f1
create function dbo.f1()
   returns datetime
as
begin
   return (select systemdate from v1)
end
go

3. 확인해보면 잘동작한다...

select dbo.f1()


/* ------------------------------------------------------------------------------ */
사례7 : 근속일수 구하는 함수 (버그 1차 수정)

덤으루 예전에 근속일수 구하는것에 대한 질문이 올라왔었는데 그때 답변용으로 만든 함수입니다.
별거 아니구 시작일자와 종료일자를 넘겨받아서 근속일수를 구하고 그것을
'00년00월00일' 과 같은 문자열로 리턴해주는 함수입니다.

사용해보지 않아서 버그가 있을수 있으니 혹시, 사용할려면 반드시 테스트후에 사용하시구
버그가 발견 된다면 리플 부탁드립니다.

--drop function dbo.fnDateDiff
create function dbo.fnDateDiff(@stdt datetime, @endt datetime)
    returns varchar(12)
as
begin
    declare @rdt varchar(12)
    declare @y int, @m int, @d int
    declare @diffmonth int

    set @diffmonth = datediff(mm, @stdt, @endt)
    if day(@endt) >= day(@stdt) - 1
        begin
            set @y = @diffmonth / 12
            set @m = @diffmonth % 12
            set @d = day(@endt) - day(@stdt) + 1
        end
    else
        begin
            set @y = @diffmonth / 12
            if @diffmonth % 12 = 0
                begin
                    set @y = @y - 1
                    set @m = @diffmonth % 12 - 1 + 12
                end
            else
                begin
                    set @m = @diffmonth % 12 - 1
                end

            set @d = day(@endt) - day(@stdt) + 1 +
                     case when month(@stdt) in (1,3,5,7,8,10,12) then 31
                          when month(@stdt) in (4,6,9,11) then 30
                          when month(@stdt) = 2 and year(@stdt) % 4 = 0 then 29
                          else  28
                     end
        end

    set @rdt = right('00'+convert(varchar(2), @y),2) + '년' +
               right('00'+convert(varchar(2), @m),2) + '월' +
               right('00'+convert(varchar(2), @d),2) + '일'
    return (@rdt)
end
go

이제 이 함수를 테스트해보자.
declare @st datetime
declare @en datetime

set @st = '1995-12-05'
set @en = '2001-10-10'

select dbo.fnDateDiff(@st, @en)

------------
05년10월06일

/* ------------------------------------------------------------------------------ */
마지막으로 time 값이 필요없다면 문자형의 사용을 고려해보구
초단위 까지 time 값이 필요하다면 datetime형을 분단위 까지의 time값만이 필요하다면
smalldatetime의 사용을 고려해보는것도 필요할듯...
/* ------------------------------------------------------------------------------ */
우선 생각나는 6가지의 사례만을 정리했고, 추후 다른 사례들이 생각나거나
Q/A등에서 발견된다면 추가할 예정입니다.

/* ------------------------------------------------------------------------------ */
1차 버그수정 : 근속일수구하는 함수에서 버그가 발견되어 수정.

/* ------------------------------------------------------------------------------ */
2차 내용추가 : 특정기간중 특정요일의 수를 구하는 함수

Q/A란에 올라온 질문

> SQL에서 예를 들어서 10월 부터 12월까지 월요일을 제외한 숫자는 몇개
> 또 일요일을 제외한 숫자몇개
> 1년에 해당하는 데이타 테이블을 따로 만들지 않고
> 검색 하는방법있으면 좀 알려주세요

/*
특정기간중 특정요일의 수를 구하는 함수

parameters : @w - 요일에 해당하는 datepart
             @st - 시작일자
             @en - 종료일자

ex ) 2003-1-1 부터 2003-3-31 까지 중에서 화요일의 수는 ?

      select dbo.weekcount(3, '2003-01-01', '2003-03-31')

*/
--drop function dbo.weekcount
create function dbo.weekcount(@w int, @st datetime, @en datetime)
   returns int
as
begin
return(select (datediff(dd, @st, @en)+1
             + datepart(w,@st)
             - case @w when 6 then 0
                       when 7 then 1
                       when 1 then 2
                       when 2 then 3
                       when 3 then 4
                       when 4 then 5
                       when 5 then 6
               end
             + case when @w < 6 and datepart(w,@st) < @w + 1 then 7 else 0 end
              ) / 7
       )
end
go


select dbo.weekcount(3, '2003-01-01', '2003-03-31') as 요일수

요일수
-----------
12

(1개 행 적용됨)

혹시 버그가 발견되거나 좀더 좋은 로직이 있다면 알려주시기 바랍니다.

/* ------------------------------------------------------------------------------ */
추가 : ASP에서 NOW()함수의 사용으로 인한 문제

Q/A란에 올라온 질문

> varchar타입으로 되있는 필드[o_date]를 이용해 정렬을 할때,
> 들어간 내용은 now()에 의해서 입력된 값이구요, (2004-02-02 오후 9:06:18)
> SELECT * FROM orders ORDER BY o_date DESC 라고 하면,
> 날짜까지만 정렬이 되고 시간부터는 정렬이 안되던데.(가령 9시보다 10시가 빠르게 나오던군요ㅡㅡ)
> ORDER BY 절에 convert를 사용해서 varchar->datetime으로 변경해서하면 가능한가요?

DB쪽에 CHAR나 VARCHAR형으로 컬럼을 잡아두고서 ASP에서 NOW() 함수를 사용하여 저장하게 되면
'2004-02-02 오전 9:06:18', '2004-02-02 오후 9:06:18'
와 같이 DB에 저장이 됩니다.
이럴경우 SQL-SERVER에서 사용하는 DATETIME과는 전혀 다른 일반 문자열로서 인식이 됩니다.
또한 날짜연산을 해야한다던지 하는경우가 발생을 하게되면
그냥 convert(datetime, 컬럼) 과 같이 사용하게될때 에러가 발생을 합니다.
이때에는 해당컬럼을 적절하게 가공을 한후에 convert() 함수를 사용하여 변환시켜주어야 합니다.

declare @dt varchar(100)
set @dt = '2004-02-02 오후 9:06:18'
select dateadd(hh, case when charindex('오후', @dt) > 0 then 12 else 0 end
                 , stuff(@dt, charindex('오', @dt), 3, ''))

------------------------------------------------------
2004-02-02 21:06:18.000

(1개 행 적용됨)

declare @dt varchar(100)
set @dt = '2004-02-02 오전 9:06:18'
select dateadd(hh, case when charindex('오후', @dt) > 0 then 12 else 0 end
                 , stuff(@dt, charindex('오', @dt), 3, ''))

------------------------------------------------------
2004-02-02 09:06:18.000

(1개 행 적용됨)

이런식으로 [오전] 이나 [오후] 라는 문자열만 space로 치환해주시면 됩니다.

하지만, 이렇게사용할경우 해당컬럼에 인덱스가 걸려있다고 하더라도 인덱스를
정상적으로 사용하지 못할수도 있고
또한, 불필요한 함수를 계속적으로 사용해야 합니다.

가능하다면, 해당컬럼을 datetime형이나 smalldatetime형으로 변환시켜 사용하시는것이
더 좋을것 같네요.

/* ------------------------------------------------------------------------------ */
추가 : 해당월의 n주차 시작일 구하는 함수

> 데이타베이스는 regdate는  (datetime)이라는 데이타타입을 가지고있습니다
> (2004-01-30 오후 10:10:25)이렇게 입력 되어진 값을 주차별로 검색을할수있는
> 기능을 추가하려고하는데 잘안되서 이렇게 도움을 요청합니다

2004년 2월을 예로들경우

첫째주가 몇일부터 몇일까지를 첫째주로 볼것인지 ?
   1. 2004-01-26 부터 2004-02-01 일까지
   2. 2004-02-01 부터 2004-02-01 일까지
   3. 2004-02-01 부터 2004-02-07 일까지
       :

등 여러가지 업무룰이 나올수가 있겠네요...

그중 1번에 해당하는 경우 하나만을 본다면

--drop function dbo.GetMonday
create function dbo.GetMonday(@yy char(4), @mm varchar(2), @wk tinyint)
   returns datetime
as
begin
   return(dateadd(dd, (@wk-1)*7,dateadd(dd, (datepart(dw, @yy+'-'[email protected]+'-01')-1)*(-1), @yy+'-'[email protected]+'-01')))
end

이러한 함수를 하나 만들어 두고서

declare @년 varchar(4), @월 varchar(2), @주차 int
set @년 = '2003'
set @월 = '2'
set @주차 = 2
select dbo.GetMonday(@년, @월, @주차)

------------------------------------------------------
2003-02-02 00:00:00.000

(1개 행 적용됨)


이런식으로 해당주차의 월요일을 구하고
이날짜에서 6일을 더하면 해당주차의 일요일을 구할수가 있습니다.

하지만, 해당업무룰이 그렇지 않다면
해당업무룰에 맞추어서 변경하셔서 사용하시면 될것같네요...

/* ------------------------------------------------------------------------------ */
추가 : 만나이 계산

> 주민번호로 만나이 계산할수 있는 쿼리를 작성중인데.. 도저히 모르겠네요..
> 주민번호로 실제나이는 구했는데..
> 고수님들 방법 좀 알려주세요..


우선, 만나이 계산 : 현재나이 - 1 에서 현재 자신의 생일이 지났으면
그대로이고, 그렇지 않다면 다시 - 1 을 한다.

72년 5월 생을 예로든다면

현재나이 2004 - 1972 + 1 = 33세

현재나이 - 1 : 32세

여기서 아직 생일이 지나지 않았으므로

만나이 : 31세가 되는것입니다.

이것을 쿼리구문으로 한다면

declare @주민번호 char(13)
set @주민번호 = '7205051000000'
select year(getdate()) -
       convert(smallint, case when substring(@주민번호,7,1) in ('1','2') then '19'
                              when substring(@주민번호,7,1) in ('3','4') then '20'
                              when substring(@주민번호,7,1) in ('9','0') then '18'
                         end + left(@주민번호,2)) -
       case when substring(@주민번호,3,4) > substring(convert(char(10),getdate(),112),5,4)
            then 1 else 0
       end

이런식이 되겠네요.

/* ------------------------------------------------------------------------------ */
추가 : 오라클의 to_date를 sql server에서 사용할경우

> 오라클에서 사용한 to_date함수 대신해 sql 함수로 바꾸워야 하는데
> 필드형식은 datetime으로 되어있구요
> inset into bill_info use_date from values (convert(char(20),cast('20941111000000' as datetime),102)
> 20941111000000==>2094-11-11 00:00:00 으로 바꾸려고 하는겁니다.
> 급한문제라서 좀 부탁 드립니다,

ms sql-server에서 시간값까지 datetime형으로 변환할려면

날짜 + space(1) + 시 + ':' + 분 + ':' + 초

의 형식으로 문자열이 지정되어야 합니다.

아래와 같은 함수를 만들어두고서 사용하시면 될듯...

--drop function dbo.to_date
create function dbo.to_date(@str char(14))
returns datetime
as
begin
   return (convert(datetime, case when len(@str) = 8 then @str
                                  else left(@str,8)+' '+
                                       substring(@str,9,2)+':'+
                                       substring(@str,11,2)+':'+
                                       substring(@str,13,2) end))
end
go

--ex :
select dbo.to_date('20941111101010')
-----------------------
2094-11-11 10:10:10.000

(1개 행 적용됨)

select dbo.to_date('20941112')
-----------------------
2094-11-12 00:00:00.000

(1개 행 적용됨)


--drop function dbo.to_char
create function dbo.to_char(@dt datetime)
returns char(14)
as
begin
   return (replace(replace(replace(convert(varchar(20), @dt, 120),':','-'),'-',' '),' ',''))
end
go

--ex :
select dbo.to_char(getdate())

--------------
20040128105301

(1개 행 적용됨)

/* ------------------------------------------------------------------------------ */
추가 : 한글 Windows, 한글 SQL 사용시 영문 날짜명칭이 필요할 경우

SET LANGUAGE us_english

select convert(varchar, getdate(), 100)

------------------------------
Jul 29 2004  4:24PM

(1개 행 적용됨)

/* ------------------------------------------------------------------------------ */

----------------------------------------------------
(^-^)(^-^)(^-^)(^-^)(^-^)(^-^)(^-^)(^-^)(^-^)(^-^)
----------------------------------------------------
  Happy SQLER...      Have a Good Time...
----------------------------------------------------


출처 :  http://sqler.pe.kr/web_board/view_list.asp?id=8279&read=363&pagec=2&found=is&part=myboard4&ser=yes

댓글목록

등록된 댓글이 없습니다.

Total 447건 1 페이지
게시물 검색

회원로그인

접속자집계

오늘
299
어제
446
최대
592
전체
38,817

그누보드5
Copyright © seobangnim.com All rights reserved.
자바스크립트를 활성화 하세요![ 브라우저에서 자바스크립트를 활성화하는 방법 ]