比較特殊的:
1. 原有 MySQL字段設置為 not null default ''
原因: ORACLE 數據庫 不允許存空字符串, 認為它跟null是一樣的 修改: 這種情況下, 在xml中, 我們暫時的處理辦法是在xml中修改原先插入的空字符串變為固定格式的字符串, 格式為"NULL_大寫的列名或者列名簡稱"
根據觀察, 存為空的情況, 可能是指, 這些數據是 作為一種默認配置的設定 目前有修改的是 a. account_performance_info_daily表中的account_type字段 => 'NULL_TYPE' b. life_cycle_saas_attachment 表中的tenant字段 => 'NULL_TENANT'
具體業務邏輯碰到沖突的地方需要進行相應更改, 一般是在select以及不同的 type case 判斷上
2. 有部分的sql 並沒有寫在xml中
這種情況可能是遇到了sql 語句 是: a. 存在了數據庫表中 例: select TABLE_NAME as tableName, DELETE_SQL as deleteSql from custom_account_data_tables b. 代碼里面動態拼出來的 customSql c. 根據model 上的注解, 通過反射, 動態拼出來的 例: DbSearchUtil
如果碰到不適配的語句時, 一般是在OracleUtil類中進行相關修改的
3. 同時刪除2表的操作,進行了修改,變成了 2個刪除語句.
例: accountMapper.deleteBenchMarkById(benchMarkIds); accountMapper.deleteBecnchMarkWeightById(benchMarkIds);
4. 不同的schema 在注入 DataSource的時候,進行一個設置.
hikariConfig.setConnectionInitSql("ALTER SESSION SET CURRENT_SCHEMA = " + schema);
有關語法的:
1. 在insert中有忽略 唯一索引檢查的操作, 語法與mysql 不同
例: <insert id="insertPermissions" parameterType="java.util.List"> insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(acl_entry(user, object_id, data_id)) */ into acl_entry("USER", object_id, data_id) <foreach collection="list" item="element" index="index" separator="union all"> ( select #{element.user, jdbcType = VARCHAR}, #{element.objectId, jdbcType = INTEGER}, #{element.dataId, jdbcType = VARCHAR} from dual) </foreach> </insert>
關於jdbcType根據現有的數據庫設定來看, 與java類型的設定建議統一如下:
與數字相關的數據庫一般使用NUMBER類型, jdbcType統一使用 NUMERIC
Java Type | jdbcType |
---|---|
String | VARCHAR |
Boolean | NUMERIC |
Integer | NUMERIC |
Long | NUMERIC |
Double | NUMERIC |
Date | DATE |
DateTime | TIMESTAMP |
更多設置可以參考 http://www.mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/type/JdbcType.html
2. SELECT * FROM ACCOUNT WHERE ID IN (1,2,3)
上述in的參數個數, Oracle 上限是1000個, 目前的處理辦法是在OracleUtil中分批查詢然后合並結果
3. Oracle 是大小寫不敏感的, 如果不使用別名, 默認返回的列名會是全部大寫
4. 列名顯式引用 需要使用雙引號
常量VARCHAR使用單引號, 使用 0 或者 1 查詢, 映射到Boolean字段上, 使用 as 別名的時候, 在表名后面一定 不要 使用, 在列名后面 可以 使用, 在where條件中, 使用原始列名 查詢 如果列名是關鍵詞,那么需要使用雙引號 顯式使用 例: select "LEVEL" as "level" from life_cycle_saas_event_type a where a."LEVEL" = '母基金'
5. 根據條件進行刪除的語句, delete 加上 join條件
例: <delete id="deleteRequirement"> delete from PRE_REQUIREMENT where rowid in ( select a.rowid from PRE_REQUIREMENT a left join pre_requirement_trace b on a.channel = b.channel where a.id = #{id} ) </delete>
6. 插入與更新操作中, 如果值可能為null, 需要顯式指定jdbcType, 不然會報錯. 例子見下一條.
7. 與mysql的replace into 語法相對應的寫法如下
<insert id="moveInternalAccountsToDel" parameterType="com.datayes.mom.instance.attribution.AccountDel"> <!-- replace into account_del(ACCOUNT_ID, ACCOUNT_DATA, EXTERNAL_SOURCE) values <foreach collection="list" item="record" separator=","> (#{record.accountID}, \#{record.accountData}, \#{record.externalSource}) </foreach> Attention: Columns referenced in the ON Clause cannot be updated FOR ORACLE --> MERGE INTO account_del A USING ( <foreach collection="list" item="record" separator=" union all " index="index"> select #{record.accountID, jdbcType=VARCHAR} as accountID, #{record.accountData, jdbcType=VARCHAR} as accountData, #{record.externalSource, jdbcType=VARCHAR} as externalSource from dual </foreach> ) B ON (A.ACCOUNT_ID=B.accountID) WHEN MATCHED THEN UPDATE set A.ACCOUNT_DATA=B.accountData, A.EXTERNAL_SOURCE=B.externalSource WHEN NOT MATCHED THEN INSERT (ACCOUNT_ID, ACCOUNT_DATA, EXTERNAL_SOURCE) VALUES(B.accountID,B.accountData,B.externalSource)
</insert>
8. Oracle中的 分頁查詢參考下面的例子, 查詢第2到11條數據
SELECT * FROM ACCOUNT OFFSET 1 ROWS FETCH NEXT 10 ROWS ONLY
9. 雖然在客戶端中可以使用分號';'作為結尾, 但是在xml中使用分號將導致 sql 執行報錯
10. 一些不同的函數
a. 獲取今天的日期
SELECT TRUNC(sysdate, 'DD') FROM dual
b. 連接多個字符串
result.userName like '%' || #{keyword} || '%'
c. 映射到boolean的例子
d. regexp 正則匹配,對應 REGEXP_LIKE
REGEXP_LIKE(查詢的字段,正則表達式)
11.插入時返回主鍵id
原語法
<insert id="insert" useGeneratedKeys="true" keyColumn="ID" keyProperty="id">
INSERT INTO xt_account_rule_info
(ACCOUNT_ID, ACCOUNT_CODE, ACCOUNT_NAME, ACCOUNT_SET_ID, ACCOUNT_SHEET_NAME, ACCOUNT_CELL, DATE_START_CELL,
UNIT_VALUE_START_CELL, ADJUST_VALUE_START_CELL, ACCUMULATE_VALUE_START_CELL)
VALUES
(#{accountId}, #{accountCode}, #{accountName}, #{accountSetId}, #{accountSheetName}, #{accountCell}, #{dateStartCell},
#{unitValueStartCell}, #{adjustValueStartCell}, #{accumulateValueStartCell})
</insert>
由於Oracle是不支持自動生成主鍵的,不像Sql或者Mysql能自動生成。所以 需要將 useGeneratedKeys 設置為false,並添加selectKey標簽,查詢對應的自增序列id並返回,如下:
<insert id="insert" useGeneratedKeys="false" keyColumn="ID" keyProperty="id">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT
get_seq_curr(sequence_name)
FROM
user_tab_identity_cols
WHERE
table_name = UPPER('xt_account_rule_info')
</selectKey>
INSERT INTO xt_account_rule_info
(ACCOUNT_ID, ACCOUNT_CODE, ACCOUNT_NAME, ACCOUNT_SET_ID, ACCOUNT_SHEET_NAME, ACCOUNT_CELL, DATE_START_CELL,
UNIT_VALUE_START_CELL, ADJUST_VALUE_START_CELL, ACCUMULATE_VALUE_START_CELL)
VALUES
(#{accountId,jdbcType=VARCHAR}, #{accountCode,jdbcType=VARCHAR}, #{accountName,jdbcType=VARCHAR}, #{accountSetId}, #{accountSheetName,jdbcType=VARCHAR}, #{accountCell,jdbcType=VARCHAR}, #{dateStartCell,jdbcType=VARCHAR},
#{unitValueStartCell,jdbcType=VARCHAR}, #{adjustValueStartCell,jdbcType=VARCHAR}, #{accumulateValueStartCell,jdbcType=VARCHAR})
</insert>
12 不支持left 與 right函數
可以通過substr函數來進行替代
substr(字符串,截取開始位置,截取長度)
截取開始位置 = 負數時,表示截取的開始位置為字符串右端向左數第 截取長度 個字符
例如:
substr(str,0,2),等價於 left(str,2)
substr(str,-2,2),等價於 right(str,2)
替換公式如下:
right(str,len) -> substr(str,-len,len)
left(str,len) -> substr(str,0,len)
特別的,對於日期類型的截取,在mysql中可以直接使用left或者right函數進行操作,在oracle中,需要將對應的日期字段轉換為標准的字符串內容后,再進行截取,比如:
在mysql中:
select left(curdate(),7) 可以得到:2022-02
在oracle中要使用substr替換
select substr(to_char(sysdate,'yyyy-MM-dd'),0,7) from dual;
13 char
對於char類型的字段,如果字段值實際長度小於字段設定長度,雖然肉眼看上去是沒有空格的,但是實際上會在尾部補充空格,所以查詢的時候,需要將字段trim之后或者將查詢條件補充空格后進行查詢。
不過一般來說,字段之所以定義為char類型,就是因為對應字段實際值會是定長的,所以一般也不需要額外的修改。對於一些特別的情況,可以按照上述方案,將查詢字段添加trim函數后進行比較:TRIM(字段)=查詢值
14 位運算
Oracle中只有位余運算:BITAND,表示返回兩個數值型數值在按位進行 AND 運算后的結果。
語法:BITAND(nExpression1, nExpression2) BITAND將 nExpression1 的每一位同 nExpression2 的相應位進行比較。如果 nExpression1 和 nExpression2 的位都是 1,相應的結果位就是 1;否則相應的結果位是 0。
與:bitand,例如: bitand(7,1) 等價於 7 & 1
15 datediff函數
在oracle中沒有datediff()函數 可以用以下方法在oracle中實現該函數的功能:
天:
ROUND(TO_NUMBER(END_DATE - START_DATE))
小時:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24)
分鍾:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60)
秒:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60)
毫秒:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60 * 60)
getFundClose
16 CONCAT 函數
在mysql中 CONCAT函數可以拼接任意數量的參數
在oracle中,CONCAT函數僅接收兩個參數的拼接,可用 || 替換
例如:
在mysql中,使用concat(1,2,3,4,5)
在oracle中,可替換為 1 || 2 || 3 || 4 || 5
17 oracle字段拼接過程中以0開頭的小數,開頭的0消失
為何小數點前0會省略,是因為oracle數據庫中存在一個隱形類型轉換,在拼接的過程中小數自動轉成字符類型,相當於調用了to_char函數,所以丟失小數點前面的0
這里操作就是把數值類型轉換為字符型,即加上to_char(字段,’fm9999999999999990.00’)
其中9代表如果存在數字則顯示數字,不存在則顯示空格; 0代表如果存在數字則顯示數字,不存在則顯示0,即占位符; fm代表刪除如果是因9帶來的空格,則刪除。
18 時間差函數:timestampdiff
語法:timestampdiff(interval, datetime1,datetime2)
結果:返回(時間2-時間1)的時間差,結果單位由interval參數給出。
單位 | MySQL(UNIT) | oracle |
---|---|---|
毫秒 | ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60 * 60) | |
秒 | second | ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60) |
分鍾 | minute | ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60) |
小時 | hour | ROUND(TO_NUMBER(END_DATE - START_DATE) * 24) |
天 | day | ROUND(TO_NUMBER(END_DATE - START_DATE)) |
周 | week | |
月 | month | trunc(months_between(END_DATE,START_DATE)) |
季 | quarter | |
年 | year | trunc(months_between(END_DATE,START_DATE)/12) |
19 中文排序問題
mysql 可以用過轉換編碼,達到使用中文拼音首字母排序的功能
order by convert ( 字段名 using gbk ) asc
在oracle中 可以使用
order by nlssort(字段名,'NLS_SORT=SCHINESE_PINYIN_M') asc
20 QUARTER() 函數,獲取日期對應的季度
在mysql 中,QUARTER(日期字段) 函數返回給定日期值(從1到4的數字)的一年的四分之一。
-
1月至3月返回1
-
4月至6月返回2
-
7月至9月返回3
-
10月至12月返回4
在oracle中,可使用 to_char(日期字段,'Q') 替換
21 字符集不匹配問題
原因可能是字段類型不一致的原因,比如,兩個字段一個是VARCHAR2,一個是NVARCHAR2
或者
是在union時,所聯接的兩塊數據,對應的字段類型不一致,一邊是VARCHAR2,一邊是NVARCHAR2。
需要先對應到具體哪個字段不一致,然后其中一個進行轉換。
目前遇到的情況,一般是查詢中,有字段是寫死的值, 用來做union或者與其他字段比較,而對應的字段是另一個數據類型。比如:
select nianyue,'全部' as VALUE_NAME_CN,count(1) shu
from (
SELECT distinct a.FUND_ID
,year(a.ESTABLISH_DATE)nianyue
from fund_class a
INNER JOIN fund_issue b on a.SECURITY_ID = b.SECURITY_ID and b.RAISE_METHOD = '1'
)a group by nianyue
select distinct a.FUND_ID
,year(b.ESTABLISH_DATE)nianyue
,d.VALUE_NAME_CN
from fund_class a
INNER JOIN fund_issue b on a.SECURITY_ID = b.SECURITY_ID and b.RAISE_METHOD = '1' and b.ESTABLISH_DATE is not null
join fund_type c on a.SECURITY_ID = c.SECURITY_ID and c.CODE_TYPE_ID = '40123'
join sys_code d on d.CODE_TYPE_ID = c.CODE_TYPE_ID and left(c.VALUE_NUM_CD,8) = d.VALUE_NUM_CD
以上兩段sql中,VALUE_NAME_CN字段,上面的對應寫死的值,下面的對應的實際字段,而實際字段的類型是NVARCHAR2,這個時候就會有字符集不一致的問題。
修改方案就是,將寫死的值的類型轉換一下就好了,Translate('全部' USING NCHAR_CS) as VALUE_NAME_CN
22 ORA-01799: 列不能外部聯接到子查詢
原因:Oracle 不支持 在 join中存在子查詢,效率太低。
解決方案:先查詢出關聯表的關聯列,條件列,以及其它需要的列,查詢結果集作為一個表,再讓其它表來關聯這個結果集
例子:
修改前
SELECT DISTINCT a.PERSON_ID personId, g.manager_type investmentType
FROM (SELECT PERSON_ID, max(POSITION) POSITION
FROM fund_manager_new
WHERE POSITION = 'FM'
and PERSON_ID in <foreach collection="personIds" item="personId" open="(" close=")" separator=",">#{personId}</foreach>
GROUP BY PERSON_ID) a
LEFT JOIN fund_manager_rating_dy g ON a.PERSON_ID = g.PERSON_ID
AND g.END_DATE = (SELECT max(END_DATE) FROM fund_manager_rating_dy)
修改后
SELECT DISTINCT a.PERSON_ID personId, g.manager_type investmentType
FROM (SELECT PERSON_ID, max(POSITION) POSITION
FROM fund_manager_new
WHERE POSITION = 'FM'
and PERSON_ID in <foreach collection="personIds" item="personId" open="(" close=")" separator=",">#{personId}</foreach>
GROUP BY PERSON_ID) a
LEFT JOIN ( select PERSON_ID,manager_type from fund_manager_rating_dy
where END_DATE = (SELECT max(END_DATE) FROM fund_manager_rating_dy)) g
on a.PERSON_ID = g.PERSON_ID order by a.PERSON_ID
23 date_sub 函數
對應替換方式如下:
oracle | oracle | |
---|---|---|
增減一小時 | date_sub(createDate, interval -1 hour) date_sub(createDate, interval 1 hour) | createDate+1/24 createDate-1/24 |
增減一天 | date_sub(createDate, interval -1 day) date_sub(createDate, interval 1 day) | createDate+1 createDate-1 |
增減一月 | date_sub(createDate, interval -1 month) date_sub(createDate, interval 1 month) | add_months(createDate, 1) add_months(createDate, -1) |
增減一季度 | date_sub(createDate, interval -3 month) date_sub(createDate, interval 3 month) | add_months(createDate, 3) add_months(createDate, -3) |
增減一年 | date_sub(createDate, interval -1 year) date_sub(createDate, interval 1 year) | add_months(createDate, 12) add_months(createDate, -12) |
listagg(c.SEC_SHORT_NAME, ',') within
GROUP (order by rownum) as SEC_SHORT_NAME,
24 field 函數 自定義排序
ORACLE可以借助DECODE函數,自定義順序排序:
DECODE(value,if 條件1,then 值1,if 條件2,then 值2,...,else 其他值)
例子:
mysql中自定義排序如下
ORDER BY FIELD(b.TYPE_NAME, '普通股票型', '偏股混合型', '短期純債型', '中長期純債型', '可轉債型', '偏債混合型', '混合債券型(一級)', '混合債券型(二級)',
'平衡混合型', '靈活配置混合型', '被動指數股票型', '增強指數股票型', '被動指數債券型', 'QDII股票型', 'QDII債券型', 'QDII混合型', 'QDII其他',
'傳統貨幣型', '短期理財型', '浮動凈值型', 'FOF', 'REITs', '保本型', '傳統封閉式', '商品型', '其他型')
等價於在oracle中的
ORDER BY DECODE(b.TYPE_NAME, '普通股票型', 1, '偏股混合型', 2, '短期純債型', 3, '中長期純債型', 4, '可轉債型', 5,
'偏債混合型', 6, '混合債券型(一級)', 7, '混合債券型(二級)', 8,
'平衡混合型', 9, '靈活配置混合型', 10, '被動指數股票型', 11, '增強指數股票型', 12,
'被動指數債券型', 13, 'QDII股票型', 14, 'QDII債券型', 15, 'QDII混合型', 16, 'QDII其他', 17,
'傳統貨幣型', 18, '短期理財型', 19, '浮動凈值型', 20, 'FOF', 21, 'REITs', 22, '保本型', 23, '傳統封閉式', 24, '商品型',25,
'其他型', 99)
25 date函數,截取日期
想將1997/1/8 10:30:27變為1997/1/8,在mysql中使用 date(時間字段)
在oracle中,使用 trunc(時間字段)
26 ORA-00907: 缺失右括號,子查詢中不能有order by
oracle子查詢中使用order by 會報錯:ORA-00907: 缺失右括號
from 子句后面的內聯視圖是可以使用order by子句進行排序的。
所以,可以將對應的oder by 子查詢語句再嵌套一層。
改造前
SELECT CLOSE_INDEX FROM
(( SELECT CLOSE_INDEX,TRADE_DATE FROM mkt_idxd
WHERE INDEX_ID = 1782 AND TRADE_DATE < #{date} ORDER BY TRADE_DATE DESC LIMIT 1)
UNION
(SELECT CLOSE_INDEX,TRADE_DATE FROM mkt_idxd
WHERE INDEX_ID = 1782 AND TRADE_DATE >= #{date} ORDER BY TRADE_DATE)) t
ORDER BY TRADE_DATE
改造后:
SELECT CLOSE_INDEX FROM
(( SELECT * from ( SELECT CLOSE_INDEX,TRADE_DATE FROM mkt_idxd
WHERE INDEX_ID = 1782 AND TRADE_DATE < #{date} and rownum=1 ORDER BY TRADE_DATE DESC ) a1 )
UNION
( SELECT * from (SELECT CLOSE_INDEX,TRADE_DATE FROM mkt_idxd
WHERE INDEX_ID = 1782 AND TRADE_DATE >= #{date} ORDER BY TRADE_DATE) a2) ) t
ORDER BY TRADE_DATE
改動點就是將原order by 子句,再嵌套一層,select * from table order by create_time 改為 select * from (原子句)
27 ORA-01791:不是SELECTed表達式
SQL 語句是先執行 distinct 去重后,再使用 order by 進行排序的。所以如果在 order by 需要排序的字段,沒有在 distinct 后的字段中,就會拋錯。
解決方案:
在 distinct 后加入需要排序的字段即可。
28 limit 問題
oracle 中沒有limit,可以使用rownum替換
但是在語句中存在order by 排序時,單純的將limit替換為rownum是不對的,因為rownum是在order by排序執行之前設置的值,針對帶有order by的語句,需要使用 fetch first關鍵字進行替換
例如:
select SECURITY_ID from MD_SECURITY order by SECURITY_ID limit 1
轉換為oracle
select SECURITY_ID from MD_SECURITY order by SECURITY_ID fetch first 1 rows only
即: 將 limit 替換為 fetch first {需要數據行數} rows only
詳細內容可參考:https://www.cnblogs.com/CandiceW/p/10030936.html
to_date(sysdate)
29 CURDATE()函數
CURDATE()函數值為不包括時分秒的值,所以替換的時候,要替換為to_date(sysdate)
30 @自定義變量問題
lag與lead函數是跟偏移量相關的兩個分析函數,通過這兩個函數可以在一次查詢中取出同一字段的前N行的數據(lag)和后N行的數據(lead)作為獨立的列,從而更方便地進行進行數據過濾。這種操作可以代替表的自聯接,並且LAG和LEAD有更高的效率。
over()表示 lag()與lead()操作的數據都在over()的范圍內,他里面可以使用partition by 語句(用於分組) order by 語句(用於排序)。partition by a order by b表示以a字段進行分組,再 以b字段進行排序,對數據進行查詢。
例如:lead(field, num, defaultvalue) field需要查找的字段,num往后查找的num行的數據,defaultvalue沒有符合條件的默認值。
窗口分析函數:
sum() over ()
下面列一下開窗函數與分析函數搭配使用的情況:
1.有partition by有order by : 在partition by分組下,按照不同的order by 字段 實現遞增匯總
2.有partition by無order by: 實現分組內所有數據的匯總
3.無partition by有order by : 直接按order by 字段實現遞增匯總
4.無partition by無order by: 所有數據相加
當然,除了使用sum() over(),還有
count() over(partition by ... order by ...):求分組后的總數。 max() over(partition by ... order by ...):求分組后的最大值。 min() over(partition by ... order by ...):求分組后的最小值。 avg() over(partition by ... order by ...):求分組后的平均值。 lag() over(partition by ... order by ...):取出前n行數據。
lead() over(partition by ... order by ...):取出后n行數據。
原sql:
(SELECT z1.*,IF(z1.SECURITY_ID=@SECURITY_ID,cast(@shu as DECIMAL(20,4)),null) AS HOLD_VOLUME_z1,
@SECURITY_ID:=SECURITY_ID,@shu:= HOLD_VOLUME_z
from
(SELECT REPORT_DATE,SECURITY_ID,TICKER_SYMBOL,SEC_SHORT_NAME,TYPE_NAME,sum(HOLD_FUND) HOLD_FUND_z,sum(HOLD_INST) HOLD_INST_z,sum(MARKET_VALUE) MARKET_VALUE_z,sum(RATIO_IN_FLOAT_A) RATIO_IN_FLOAT_A_z,sum(HOLD_VOLUME) HOLD_VOLUME_z
from fund_mt_holdkey_type
where CATEGORY in <foreach collection="strategyCodes" item="code" open="(" close=")" separator=",">#{code}</foreach>
group by REPORT_DATE,SECURITY_ID,TICKER_SYMBOL,SEC_SHORT_NAME,TYPE_NAME
order by SECURITY_ID,REPORT_DATE) z1,(SELECT @SECURITY_ID:=NULL,@shu:= null)r)
改造后sql:
(SELECT
case when z1_pre = SECURITY_ID then HOLD_VOLUME_z1_1 end as HOLD_VOLUME_z1,
z1_1.*
from (SELECT lag(z1.SECURITY_ID, 1, null) over (order by SECURITY_ID,REPORT_DATE) as z1_pre,
lag(cast(z1.HOLD_VOLUME_z as DECIMAL(20,4)), 1, null) over (order by SECURITY_ID,REPORT_DATE) AS HOLD_VOLUME_z1_1,
z1.*
from
(SELECT REPORT_DATE,SECURITY_ID,TICKER_SYMBOL,SEC_SHORT_NAME,TYPE_NAME,sum(HOLD_FUND) HOLD_FUND_z,sum(HOLD_INST) HOLD_INST_z,sum(MARKET_VALUE) MARKET_VALUE_z,sum(RATIO_IN_FLOAT_A) RATIO_IN_FLOAT_A_z,sum(HOLD_VOLUME) HOLD_VOLUME_z
from fund_mt_holdkey_type
where CATEGORY in <foreach collection="strategyCodes" item="code" open="(" close=")" separator=",">#{code}</foreach>
group by REPORT_DATE,SECURITY_ID,TICKER_SYMBOL,SEC_SHORT_NAME,TYPE_NAME
order by SECURITY_ID,REPORT_DATE) z1) z1_1)
31 substring 函數
直接替換為substr函數即可
32 year 函數獲取日期的年份
year ( 日期字段 )
轉換為oracle函數為:
extract(year from 日期字段)
33 force index 強制使用索引
SELECT /*+index(t pk_emp)*/* FROM EMP T --強制索引,/*.....*/第一個星星后不能有空格,里邊內容結構為:加號index(表名 空格 索引名)。 --如果表用了別名,注釋里的表也要使用別名。
34 join時沒有on或者where條件
使用join
或時inner join
,on
條件是可選的。這與ANSI標准不同,並且與幾乎所有其他數據庫不同。效果是cross join