2013-05-06 104 views
10

我想創建一個varchar列轉換日期的索引。我在做這樣的事情:PostgreSQL創建索引從字符串轉換到日期

CREATE INDEX date_index ON table_name (CAST(varchar_column AS DATE)); 

,我發現了錯誤:functions in index expression must be marked IMMUTABLE但我不知道爲什麼,劇組至今不依賴於時區或類似的東西(這使得強制轉換爲帶有時區的時間戳發出此錯誤)。

任何幫助?

+0

有沒有辦法在pg轉換日期通過特定的格式規則?如果格式必須被猜測,SQL Server不喜歡做這樣的轉換。 – user2246674 2013-05-06 19:23:24

回答

10

您的第一個錯誤是將日期存儲爲varchar列。你不應該那樣做。

適合您的問題的解決方法是將列轉換爲真正的date

現在我敢肯定的答案,這種說法是「我沒有設計的數據庫,我不能改變它」,所以這裏是一個解決辦法:

CASTto_char()都不是一成不變的,因爲他們可以根據當前會話的設置,爲相同的輸入值返回不同的值。

如果您知道表格中所有值的格式一致(如果您有 - 可以將列轉換爲實際的date列),那麼您可以創建自己的函數,將varchar轉換爲一個日期並被標記爲不可變。

create or replace function fix_bad_datatype(the_date varchar) 
    returns date 
    language sql 
    immutable 
as 
$body$ 
    select to_date(the_date, 'yyyy-mm-dd'); 
$body$ 
ROWS 1 
/

有了這個定義,你可以創建表達式的索引:

CREATE INDEX date_index ON table_name (fix_bad_datatype(varchar_column)); 

但是你使用正是函數調用查詢以便Postgres使用它:

select * 
from foo 
where fix_bad_datatype(varchar_column) < current_date; 

請注意,如果您的varchar列中只有一個「非法」值,則此方法將失敗。唯一明智的解決方案存儲日期爲date s,

+2

@Topo:'to_date()'也是'STABLE',而不是'IMMUTABLE',即使這個很可能。 [Here](http://www.postgresql.org/message-id/flat/[email protected]#[email protected]s)是關於devel列表的一個討論,爲什麼會這樣。 – 2013-05-06 19:43:28

+0

但是,當我使用這樣的查詢'select * from foo where fix_bad_datatype(varchar_column)> ='2015-02-05':: date;'而不使用'current_date'時,需要比執行沒有索引的時間更長的時間。任何想法? – 2015-10-07 06:13:11

+0

@MarlonAbeykoon:https://wiki.postgresql.org/wiki/Slow_Query_Questions – 2015-10-07 06:13:58

2

請提供數據庫版本,表ddl和一些示例數據。

會使你自己的不可變函數做你想做的事情嗎?也看看在文檔中創建一個新的演員,看看是否爲你做了任何事情。

create table emp2 (emp2_id integer, hire_date VARCHAR(100)); 

insert into emp2(hire_date) 
select now(); 

select cast(hire_date as DATE) 
from emp2 


CREATE FUNCTION my_date_cast(VARCHAR) RETURNS DATE 
    AS 'select cast($1 as DATE)' 
    LANGUAGE SQL 
    IMMUTABLE 
    RETURNS NULL ON NULL INPUT; 


CREATE INDEX idx_emp2_hire_date ON emp2 (my_date_cast(hire_date)); 
+0

我們如何查詢單獨的索引? – Chris 2015-06-18 22:00:25