2016-09-27 272 views
1

我想阻止任何沒有時區的時間戳被插入到PostgreSQL SQL函數中。唯一的辦法我設法拿出不起作用,因爲Postgres的似乎只是忽略任何時區的字符串後綴,而是使用了時區從服務器:PostgreSQL:如何測試時間戳是否有時區?

hostname:~ username$ date 
Tue Sep 27 15:30:16 CEST 2016 

hostname:~ username$ uname -a 
Darwin hostname.domain 14.5.0 Darwin Kernel Version 14.5.0: Mon Aug 29 21:14:16 PDT 2016; root:xnu-2782.50.6~1/RELEASE_X86_64 x86_64 

hostname:~ username$ psql -U postgres 
psql (9.5.3) 
Type "help" for help. 

postgres=# SELECT extract(TIMEZONE FROM '2016-09-19 01:00:00'::timestamptz); 
date_part 
----------- 
     7200 
(1 row) 

postgres=# SELECT extract(TIMEZONE FROM '2016-09-19 01:00:00+0200'::timestamptz); 
date_part 
----------- 
     7200 
(1 row) 

postgres=# SELECT extract(TIMEZONE FROM '2016-09-19 01:00:00+0800'::timestamptz); 
date_part 
----------- 
     7200 
(1 row) 

我有一種感覺,我通常誤解的東西。誰能幫忙?

更新20160928:

爲了給一些解釋性背景下,這是我的數據庫(精簡到什麼是眼下的問題必不可少):

CREATE DATABASE my_db; 
CREATE TABLE my_table 
(
    id serial PRIMARY KEY, 
    timestamp_utc timestamp with time zone NOT NULL, 
    title text NOT NULL 
); 

,這是我的函數以其當前形式插入數據:

CREATE FUNCTION insert_row 
(
    p_timestamp_utc timestamp with time zone, 
    p_title   text 
) 
RETURNS integer 
LANGUAGE SQL 
SECURITY DEFINER 
VOLATILE 
AS 
$BODY$ 
    INSERT INTO my_table 
       ( timestamp_utc title) 
     VALUES (p_timestamp_utc, p_title) 
     RETURNING id; 
$BODY$; 

我創建了一個SQLFiddle;創建有保留,雖然沒有功能...

問題:

調用函數成功,即使時間戳參數不攜帶一個時區:

SELECT insert_row('2016-09-01 01:00:00'::timestamptz, 'some title'); 

,我需要找到一種使這個函數調用失敗的方法。

原因爲什麼我需要做到這一點是因爲我想定義什麼時區是由代碼強制執行的;另一種選擇是數據庫服務器和客戶端在某種程度上隱含地/默默地同意一個約定 - 並且這聽起來不像是一個聰明的舉動......

回答

1

在PostgreSQL中,時區信息不會與timestamp with time zone一起存儲。 相反,當轉換爲其內部表示時,時間戳會轉換爲UTC

timestamp with time zone被轉換爲字符串時,例如,當它被顯示時,它將被轉換爲在TimeZone配置參數中設置的時區。

當您使用EXTRACT來檢索時區信息時會發生同樣的情況。這些文檔有點不清楚。

所以,如果你的時區設置是這樣的:

test=> SHOW TimeZone; 
    TimeZone 
--------------- 
Europe/Vienna 
(1 row) 

您將獲得:

test=> SELECT extract(TIMEZONE FROM '2016-01-01 00:00:00-07'::timestamptz); 
date_part 
----------- 
     3600 
(1 row) 

因爲歐洲中部時間從UTC偏移1小時,

test=> SELECT extract(TIMEZONE FROM '2016-08-01 00:00:00-07'::timestamptz); 
date_part 
----------- 
     7200 
(1 row) 

因爲中歐夏令時從UTC抵消2小時

+0

感謝您的信息!:-)雖然你的回答肯定是內容豐富的,但它並沒有真正幫助我防止任何沒有時區的時間戳插入到我的數據庫中,是嗎? – ssc

+0

我試圖解決你的「一般誤解」。爲了讓我能夠幫助你解決問題,你能解釋一下你插入PostgreSQL SQL函數*的含義嗎? –

相關問題