Cách chuyển đổi cột dấu thời gian của SQL Server sang định dạng ngày giờ


90

Vì SQL Server trả về dấu thời gian như vậy 'Nov 14 2011 03:12:12:947PM', có một số cách dễ dàng để chuyển đổi chuỗi sang định dạng ngày tháng như 'Ymd H: i: s'.

Cho đến nay tôi sử dụng

date('Y-m-d H:i:s',strtotime('Nov 14 2011 03:12:12:947PM'))

Câu trả lời:


252

TIMESTAMPKiểu dữ liệu của SQL Server không liên quan gì đến ngày và giờ!

Nó chỉ là một biểu diễn thập lục phân của một số nguyên 8 byte liên tiếp - nó chỉ tốt để đảm bảo một hàng không thay đổi kể từ khi nó được đọc.

Bạn có thể đọc số nguyên thập lục phân hoặc nếu bạn muốn a BIGINT. Ví dụ:

SELECT CAST (0x0000000017E30D64 AS BIGINT)

Kết quả là

400756068

Trong các phiên bản SQL Server mới hơn, nó được gọi RowVersion- vì đó thực sự là như vậy. Xem tài liệu MSDN trên ROWVERSION :

Là một kiểu dữ liệu hiển thị các số nhị phân được tạo tự động, duy nhất trong cơ sở dữ liệu. rowversion thường được sử dụng như một cơ chế cho các hàng trong bảng dập phiên bản. Kiểu dữ liệu chuyển đổi hàng chỉ là một số tăng dần và không bảo toàn ngày hoặc giờ . Để ghi ngày hoặc giờ, hãy sử dụng kiểu dữ liệu datetime2.

Vì vậy, bạn không thể chuyển đổi SQL Server TIMESTAMPthành ngày / giờ - nó không phải là ngày / giờ.

Nhưng nếu bạn đang nói dấu thời gian nhưng thực sự ý bạn là một DATETIMEcột - thì bạn có thể sử dụng bất kỳ định dạng ngày hợp lệ nào được mô tả trong chủ đề CAST và CONVERT trong trợ giúp MSDN. Chúng được xác định và hỗ trợ "out of the box" bởi SQL Server. Bất kỳ thứ gì khác không được hỗ trợ, ví dụ như bạn phải thực hiện nhiều quá trình truyền và nối thủ công (không được khuyến khích).

Định dạng bạn đang tìm kiếm có vẻ giống với ODBC canonical (style = 121):

DECLARE @today DATETIME = SYSDATETIME()

SELECT CONVERT(VARCHAR(50), @today, 121)

cho:

2011-11-14 10:29:00.470

SQL Server 2012 cuối cùng sẽ có một FORMATchức năng để thực hiện định dạng tùy chỉnh ......


5
Có lẽ mối quan tâm lớn nhất của tôi với SQL Server. Tại sao lại gọi nó là dấu thời gian nếu tôi không thể biết thời gian với nó?
BelgoCanadian

1
@BelgoCanadian: hỏi Sybase - đó là một tính năng đó là được Sybase / SQL Server mãi mãi .....
marc_s

1
@BelgoCanadian Bạn nên vui mừng khi biết nó bây giờ được gọi là rowversion docs.microsoft.com/en-us/sql/t-sql/data-types/...
Jason S

TIMESTAMPcột loại
Ghilteras

4

Cách đơn giản nhất để làm điều này là:

SELECT id,name,FROM_UNIXTIME(registration_date) FROM `tbl_registration`;

Điều này làm cho cột ngày ở định dạng có thể đọc được ít nhất. Hơn nữa nếu bạn muốn thay đổi định dạng te bấm vào đây .


11
câu hỏi là SQLServer, không MySQL
Mike M

4

Sử dụng truyền, bạn có thể lấy ngày từ trường dấu thời gian:

SELECT CAST(timestamp_field AS DATE) FROM tbl_name

18
Điều này dường như không hoạt động:Explicit conversion from data type timestamp to date is not allowed.
jocull

Ý kiến ​​tồi. Trường dấu thời gian chỉ là một chuỗi. Bạn có thể gặp may mắn và được hẹn hò, nhưng ngày đó sẽ chẳng có ý nghĩa gì. Bạn nên chuyển thành BIGINT nếu bạn muốn một số thập phân, thay vì hex. Dấu thời gian hiện được gọi là rowversion docs.microsoft.com/en-us/sql/t-sql/data-types/…
Jason S

3

Đồng nghiệp của tôi đã giúp tôi điều này:

select CONVERT(VARCHAR(10), <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(VARCHAR(10), <tms_column>, 112);

hoặc là

select CONVERT(DATE, <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(DATE, <tms_column>, 112);

3

Hoạt động tốt, ngoại trừ thông báo này:

Không cho phép chuyển đổi ngầm định từ kiểu dữ liệu varchar sang dấu thời gian. Sử dụng hàm CHUYỂN ĐỔI để chạy truy vấn này

Vì vậy, có, TIMESTAMP( RowVersion) KHÔNG PHẢI LÀ NGÀY :)

Thành thật mà nói, tôi đã lăn lộn khá lâu để tìm cách chuyển nó thành ngày tháng.

Cách tốt nhất là chuyển đổi nó sang INTvà so sánh. Đó là những gì loại này có nghĩa là.

Nếu bạn muốn có một ngày - chỉ cần thêm một Datetimecột và sống hạnh phúc mãi mãi :)

cổ vũ mac


1
Hoặc BIGINT vì nó là 8 byte
Jason S

2

"Bạn tiếp tục sử dụng từ đó. Tôi không nghĩ nó có nghĩa như những gì bạn nghĩ." - Inigo Montoya

Dấu thời gian hoàn toàn không có mối quan hệ với thời gian như marc_s đã nói ban đầu.

declare @Test table (
     TestId int identity(1,1) primary key clustered
    ,Ts     timestamp
    ,CurrentDt datetime default getdate()
    ,Something varchar(max)
)

insert into @Test (Something)
    select name from sys.tables
waitfor delay '00:00:10'

insert into @Test (Something)
    select name from sys.tables

select * from @Test

Lưu ý trong đầu ra rằng Ts (hex) tăng một cho mỗi bản ghi, nhưng thời gian thực có khoảng cách là 10 giây. Nếu nó liên quan đến thời gian thì sẽ có một khoảng trống trong dấu thời gian để tương ứng với sự khác biệt về thời gian.


0

Sau khi thực hiện chuyển đổi thành CONVERT số nguyên (BIGINT, [timestamp]) dưới dạng Dấu thời gian, tôi đã nhận được kết quả như

446701117 446701118 446701119 446701120 446701121 446701122 446701123 446701124 446701125 446701126

Có, đây không phải là ngày và giờ, Đó là số sê-ri


0

đối với tôi hoạt động: TO_DATE ('19700101', 'yyyymmdd') + (TIME / 24/60/60) (oracle DB)


0

Tôi đã gặp vấn đề tương tự với dấu thời gian, ví dụ: '29 -JUL-20 04.46.42.000000000 PM '. Tôi muốn chuyển nó thành định dạng 'yyyy-MM-dd'. Giải pháp cuối cùng phù hợp với tôi là

CHỌN TO_CHAR (mytimestamp, 'YYYY-MM-DD') TỪ bảng của tôi;


0

Tôi sẽ giả sử rằng bạn đã thực hiện một kết xuất dữ liệu dưới dạng các câu lệnh chèn và bạn (hoặc bất kỳ ai Google gửi điều này) đang cố gắng tìm ra ngày và giờ hoặc dịch nó để sử dụng ở nơi khác (ví dụ: để chuyển đổi sang chèn MySQL). Điều này thực sự dễ dàng trong bất kỳ ngôn ngữ lập trình nào.

Hãy làm việc với điều này:

CAST(0x0000A61300B1F1EB AS DateTime)

Biểu diễn Hex này thực sự là hai phần tử dữ liệu riêng biệt ... Ngày và Giờ. Bốn byte đầu tiên là ngày tháng, bốn byte thứ hai là thời gian.

  • Ngày là 0x0000A613
  • Giờ là 0x00B1F1EB

Chuyển đổi cả hai phân đoạn thành số nguyên bằng cách sử dụng ngôn ngữ lập trình mà bạn chọn (đó là chuyển đổi trực tiếp hex sang số nguyên, được hỗ trợ trong mọi ngôn ngữ lập trình hiện đại, vì vậy, tôi sẽ không lãng phí dung lượng với mã có thể là ngôn ngữ lập trình hoặc có thể không bạn đang làm việc).

  • Ngày của 0x0000A613 trở thành 42515
  • Thời gian của 0x00B1F1EB trở thành 11661803

Bây giờ, phải làm gì với những số nguyên đó:

Ngày

Ngày kể từ ngày 01/01/1900 và được biểu thị dưới dạng ngày. Vì vậy, hãy thêm 42.515 ngày vào 01/01/1900, và kết quả của bạn là 27/05/2016.

Thời gian

Thời gian phức tạp hơn một chút. Lấy INT đó và làm như sau để tính thời gian của bạn tính bằng micro giây kể từ nửa đêm (mã giả):

TimeINT=Hex2Int(HexTime)
MicrosecondsTime = TimeINT*10000/3

Từ đó, sử dụng các lệnh gọi hàm yêu thích của ngôn ngữ của bạn để dịch micro giây (38872676666,7 µs trong ví dụ trên) thành thời gian.

Kết quả sẽ là 10: 47: 52,677


-1

Một số trong số chúng thực sự ẩn đến một ngày-giờ từ SQL Server 2008 trở đi.

Hãy thử truy vấn SQL sau và bạn sẽ thấy:

SELECT CAST (0x00009CEF00A25634 AS datetime)

Ở trên sẽ dẫn đến 2009-12-30 09:51:03:000nhưng tôi đã gặp những cái thực sự không liên kết với ngày-giờ.


1
Đừng làm vậy. Bạn có thể gặp may mắn và nhận được một chuyển đổi nhưng ngày giờ sẽ vô nghĩa và gây hiểu lầm. Dấu thời gian chỉ là một số thứ tự và hiện được gọi là phiên bản hàng docs.microsoft.com/en-us/sql/t-sql/data-types/… . Nếu bạn muốn một số thập phân chỉ cần truyền đến BIGINT
Jason S


-3

Không chắc liệu tôi có thiếu thứ gì đó ở đây hay không nhưng bạn không thể chỉ chuyển đổi dấu thời gian như thế này:

CONVERT(VARCHAR,CAST(ZEIT AS DATETIME), 110)

Bạn đã thử cái này chưa? TIMESTAMP không liên quan đến DATE.
Sean Pearce,

Tôi đang sử dụng nó trên SQL Server 2008
Daniel

Một lần nữa, đừng cố truyền đến ngày giờ. Nó chỉ đơn giản là một dãy số nguyên ở dạng thập lục phân. Chỉ cần truyền đến BIGINT.
Jason S
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.