2012-10-01 41 views
8

Tôi phải nhập dữ liệu không có thông tin múi giờ trong đó (tuy nhiên, tôi biết múi giờ cụ thể của dữ liệu tôi muốn nhập), nhưng tôi cần định dạng timestamp with time zone trong cơ sở dữ liệu. Khi tôi nhập nó và đặt kiểu dữ liệu dấu thời gian thành timestamp with time zone, Postgres sẽ tự động giả định rằng dữ liệu trong bảng là từ múi giờ của tôi và gán múi giờ của tôi cho nó. Thật không may dữ liệu tôi muốn nhập không phải là từ khung thời gian của tôi, vì vậy điều này không hoạt động.Thay đổi giá trị múi giờ của dữ liệu

Cơ sở dữ liệu cũng chứa dữ liệu với các múi giờ khác nhau. Tuy nhiên, múi giờ trong một bảng luôn giống nhau.

Bây giờ, tôi có thể đặt múi giờ của cơ sở dữ liệu thành múi giờ của dữ liệu tôi muốn nhập trước khi nhập dữ liệu (sử dụng lệnh SET time zone) và thay đổi trở lại múi giờ của mình sau khi quá trình nhập hoàn tất và Tôi khá chắc chắn đã được lưu trữ dữ liệu sẽ không bị ảnh hưởng bởi sự thay đổi múi giờ của cơ sở dữ liệu. Nhưng điều này có vẻ là một cách tiếp cận khá bẩn và có thể gây ra vấn đề sau này.

Tôi tự hỏi liệu có cách nào thanh lịch hơn để chỉ định múi giờ cho việc nhập mà không có dữ liệu múi giờ trong chính dữ liệu không?

Ngoài ra, tôi chưa tìm thấy cách chỉnh sửa thông tin múi giờ sau khi nhập. Có cách nào không chuyển đổi, nhưng chỉ cần chỉnh sửa múi giờ cho toàn bộ bảng, giả sử rằng toàn bộ bảng có cùng một múi giờ bù đắp (tức là nếu một sai đã được gán khi nhập/nhập dữ liệu)?

Edit:
tôi quản lý để xác định một múi giờ sau khi nhập khẩu, lệnh toàn bộ con người:

set session time zone 'UTC'; 
COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
set session time zone 'CET'; 

Dữ liệu sau đó được nhập khẩu bằng cách sử dụng múi giờ phiên. Tôi cho rằng điều này không ảnh hưởng đến bất kỳ truy vấn nào khác trên cơ sở dữ liệu cùng một lúc từ các kết nối khác?

Chỉnh sửa 2:
tôi phát hiện ra làm thế nào để thay đổi múi giờ của một bảng sau:
PostgreSQL update time zone offset

Tôi cho rằng đó là thanh lịch hơn để thay đổi múi giờ của bảng sau khi nhập khẩu sau đó sử dụng phiên để thay đổi múi giờ địa phương tạm thời. Giả sử toàn bộ bảng có cùng múi giờ.

Vì vậy, các mã sẽ là bây giờ cái gì dọc theo dòng:

COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
UPDATE tbl SET <tstz_field> = <tstz_field> AT TIME ZONE '<correct_time_zone>'; 
+0

How are you thực hiện nhập khẩu của bạn? bạn không thể chỉ định múi giờ trong khi nhập? – ertx

+0

Cảm ơn mẹo, tôi đã cập nhật bài đăng nhưng tôi không chắc chắn loại múi giờ phiên hiệu ứng nào có trên các quy trình khác trong cơ sở dữ liệu tại thời điểm thực thi? – harbun

Trả lời

11

Đó là rất nhiều hiệu quả hơn để thiết lập múi giờ cho phiên nhập của bạn hơn để cập nhật các giá trị sau này.

Tôi có ấn tượng rằng bạn nghĩ múi giờ giống như cài đặt áp dụng cho các giá trị không thay đổi trong bảng. Nhưng nó không giống như vậy chút nào. Hãy nghĩ về nó như một công cụ sửa đổi đầu vào/đầu ra. Giá trị thực tế timestamp (có hoặc không có múi giờ) là luôn là được lưu trữ dưới dạng dấu thời gian UTC nội bộ (số giây kể từ '2000-01-01 00:00').Rất nhiều chi tiết hơn:

Các UPDATE trong ví dụ thứ hai của bạn tăng gấp đôi kích thước của bảng, như mọi hàng duy nhất không còn giá trị và một phiên bản mới được bổ sung (đó là cách UPDATE làm việc với MVCC trong Postgres). Ngoài các hoạt động tốn kém, VACUUM sẽ phải làm nhiều việc hơn sau đó để làm sạch bảng sưng lên. Rất Không Hiệu Quả.

Đó là hoàn toàn an toàn đến SET múi giờ địa phương cho phiên. Điều này không ảnh hưởng đến hoạt động đồng thời theo bất kỳ cách nào. Btw., SET SESSION giống với số SET đơn giản vì mặc định SESSION là mặc định.

Nếu bạn muốn trở thành hoàn toàn chắc chắn, bạn có thể giới hạn các thiết lập để hiện hành giao dịch với SET LOCAL. Tôi xin trích dẫn hướng dẫn here

Ảnh hưởng của SET LOCAL cuối cùng chỉ đến khi kết thúc giao dịch vãng lai, cho dù cam kết hay không. Một trường hợp đặc biệt là SET sau bởi SET LOCAL trong một giao dịch duy nhất: giá trị SET LOCAL sẽ thấy cho đến khi kết thúc giao dịch, nhưng sau đó (nếu giao dịch là cam kết) giá trị SET sẽ có hiệu lực.

Đặt nhau:

BEGIN; 
SET LOCAL timezone = 'UTC'; 
COPY tabledata FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
COMMIT; 

Kiểm tra:

SHOW timezone; 
+0

** Chính xác ** những gì tôi cần biết, giải thích tuyệt vời. Danke Erwin. :) – harbun

+0

@harbun: Bitteschön. :) –

Các vấn đề liên quan