Oracle遷移PostgreSQL經驗總結(SQL部分)
Oracle遷移PostgreSQL數據庫經驗總結(SQL部分,未完待續),本文只包括了我工作中接觸到或者用到的技術點,其實兩個數據庫設計上的差異是很大的,但是Oracle數據庫有的功能,PostgreSQL大體上也都能實現。
序號 | 項目 | Oracle | PostgreSQL | </tr>||||||||||||||||||||||||
1 | 當前時間 | SYSDATE | 可全部使用current_timestamp替換 | </tr>||||||||||||||||||||||||
2 | 序列 | SEQNAME.NEXTVAL | NEXTVAL('SEQNAME') | </tr>||||||||||||||||||||||||
3 | 固定值列 | SELECT '1' AS COL1 | SELECT CAST('1' AS TEXT) AS COL1 | </tr>||||||||||||||||||||||||
4 | NVL | NVL函數 | NVL可以用COALESCE函數替換 | </tr>||||||||||||||||||||||||
5 | 類型自動轉換 | Oracle某些情況下支持類型自動轉換 | 會出現類型不匹配等錯誤,需要在Java或者sql中進行類型轉換,使類型匹配 | </tr>||||||||||||||||||||||||
6 | INSTR函數 | instr('str1','str2') | strpos('str1','str2') | </tr>||||||||||||||||||||||||
7 | 外連接 | Oracle可簡寫為(+) | 用LEFT JOIN等語句替換 | </tr>||||||||||||||||||||||||
8 | 層次查詢 | START WITH語句 CONNECT BY語句 |
用WITH RECURSIVE語句 | </tr>||||||||||||||||||||||||
9 | 數據庫對象大小寫 | 不區分大小寫 | 創建數據庫對象時要小寫,這樣才不區分SQL的大小寫 | </tr>||||||||||||||||||||||||
10 | 同義詞 | Oracle支持同義詞 | 用視圖代替 | </tr>||||||||||||||||||||||||
11 | DUAL | SELECT 1+1 FROM DUAL | SELECT 1+1 或者 CREATE VIEW dual AS SELECT current_timestamp |
</tr>
||||||||||||||||||||||||
12 | ROWNUM | ROWNUM關鍵字 | 兩種情況: 1.限制結果集數量,用于翻頁等: SELECT * FROM T LIMIT 5 OFFSET 0 2.生成行號: ROW_NUMBER() OVER() |
</tr>
||||||||||||||||||||||||
13 | DECODE等判斷函數 | DECODE() | 用標準的CASE WHEN THEN ELSE END語句替換 | </tr>||||||||||||||||||||||||
14 | TO_CHAR | TO_CHAR(COL,FMT),格式化字符串可以為空 | TO_CHAR(COL1,'FM999999'),9的個數為字段長度,詳細定義見: http://www.postgresql.org/docs/9.4/static/functions-formatting.html |
</tr>
||||||||||||||||||||||||
15 | TO_NUMBER | TO_NUMBER(COL,FMT),格式化字符串可以為空 | TO_NUMBER(COL1,'999999'),9的個數為字段長度,詳細定義見: http://www.postgresql.org/docs/9.4/static/functions-formatting.html |
</tr>
||||||||||||||||||||||||
16 | NULL和'' | ORACLE認為''等同于NULL | NULL和''不同 | </tr>||||||||||||||||||||||||
17 | NULL和'' | LENGTH('')為NULL | LENGTH('')為0 | </tr>||||||||||||||||||||||||
18 | NULL和'' | TO_DATE('','YYYYMMDD')為空 | TO_DATE('','YYYYMMDD')為0001-01-01 BC | </tr>||||||||||||||||||||||||
19 | NULL和'' | TO_NUMBER('',1)為NULL | TO_NUMBER('',1),報錯 | </tr>||||||||||||||||||||||||
20 | NULL和'' | INSERT INTO TEST(VALUE4)VALUES('') [Result]VALUE4=NULL (注:VALUE3字段為數值類型) |
INSERT INTO TEST(VALUE4)VALUES('') VALUE4=NULL |
</tr>
||||||||||||||||||||||||
21 | NULL和'' | INSERT INTO TEST(VALUE4)VALUES('') [Result]VALUE4=NULL (注:VALUE3字段為字符類型) |
INSERT INTO TEST(VALUE4)VALUES('') VALUE4='' |
</tr>
||||||||||||||||||||||||
22 | NULL和'' | INSERT INTO TEST(VALUE4)VALUES(TO_DATE('','YYYYMMDD')) [Result]VALUE4=NULL (注:VALUE3字段為時間類型) |
INSERT INTO TEST(VALUE6)VALUES(TO_DATE('','YYYYMMDD')) [Result]VALUE6=0001-01-01 BC |
</tr>
||||||||||||||||||||||||
23 | ADD_MONTHS | ADD_MONTHS(DATE,INT) | CREATE FUNCTION add_months(date, int) RETURNS date AS 'SELECT ($1 +($2::text||'' month'')::interval)::date' LANGUAGE 'sql' 或SQL: SELECT ($1 +($2::text||' month')::interval) |
</tr>
||||||||||||||||||||||||
24 | LAST_DAY | LAST_DAY(DATE) | 創建函數來解決 CREATE OR REPLACE FUNCTION last_day(date) RETURNS date AS $$ SELECT (date_trunc('MONTH', $1) + INTERVAL '1 MONTH - 1 day')::date; $$ LANGUAGE 'sql'; 或SQL: SELECT (date_trunc('MONTH', $1) + interval '1 month - 1 day')::date; |
</tr>
||||||||||||||||||||||||
25 | MONTHS_BETWEEN | MONTHS_BETWEEN(DATE,DATE) | 創建函數來解決 CREATE FUNCTION MONTH_BETWEEN(d1 timestamp,d2 timestamp) RETURNS NUMERIC AS 'SELECT (extract(year from age(d1,d2))*12 + extract(month from age(d1,d2)))::integer' LANGUAGE 'sql'; |
</tr>
||||||||||||||||||||||||
26 | BITAND | BITAND(A,B) | A & B | </tr>||||||||||||||||||||||||
27 | MINUS | MINUS語句 | 以EXCEPT語句來替代 | </tr>||||||||||||||||||||||||
28 | BIN_ | SELECT BIN_TO_NUM(1,0,1,0) AS VALUE1 FROM DUAL | SELECT CAST(B'1010' AS INTEGER) AS VALUE1 | </tr>||||||||||||||||||||||||
29 | UPDATE語句列列表 | UPDATE accounts SET (contact_last_name, contact_first_name) = (SELECT last_name, first_name FROM salesmen WHERE salesmen.id = accounts.sales_id); |
不支持該語法,需要拆分為多個單獨的列 | </tr>||||||||||||||||||||||||
30 | SUBSTR函數 | 如果從第一個開始取子串,可以從0開始,也可以從1開始,如果不是第一個開始,則從1開始計數,可以為負值,從字符串結尾計數,用于取最后幾位。 | 從1開始計數。如果要取最后幾位,可以用RIGHT函數解決。 | </tr>||||||||||||||||||||||||
31 | 子查詢別名 | 如果FROM后只有一個子查詢,該子查詢可以沒有別名 | 必須有別名 | </tr>||||||||||||||||||||||||
32 | 列(別)名為關鍵字 | Oracle中比如name,type這樣的關鍵字可以直接作為列的別名,比如:select xx name from t | 需要加as,比如select xx as name from t | </tr>||||||||||||||||||||||||
33 | 當前登錄用戶 | SELECT USER FROM DUAL | select current_user | </tr>||||||||||||||||||||||||
34 | ALL_COL_COMMENTS | 通過SELECT * FROM ALL_COL_COMMENTS可以獲得列注釋信息 | select s.column_name as COLUMN_NAME,coalesce(col_description(c.oid,ordinal_position) ,s.column_name) as COMMENTS from information_schema.columns s,pg_class c where s.table_name = 'ac01_si' and s.table_name = c.relname and s.table_schema = current_schema() PG需要通過col_description獲得列注釋信息 |
</tr>
||||||||||||||||||||||||
35 | 修改表字段類型 | 1.如果字段無數據,可直接修改 2.如果有數據且新類型和原類型兼容,也可以直接修改 3.如果不兼容,可通過對原字段改名,然后增加新字段,再通過UPDATE語句對數據進行處理 |
1.如果新類型和原類型兼容,可直接修改 2.如果不兼容,需要使用USING關鍵字然后提供一個類型轉換的表達式 |
</tr>
||||||||||||||||||||||||