本文將說明 Oracle® 和 MySQL 適用的 Cloud SQL 之間的基本查詢差異,以及 Oracle 中的功能如何對應至 MySQL 適用的 Cloud SQL 中的功能。並概略說明 Cloud SQL for MySQL 的效能考量事項,以及如何分析及改善Google Cloud的查詢效能。雖然本文會介紹如何為 MySQL 適用的 Cloud SQL 最佳化儲存的程序和觸發事件,但不會說明如何將 PL/SQL 程式碼轉譯為 MySQL 儲存的程序和函式。
將查詢從 Oracle 資料庫轉換為 Cloud SQL for MySQL 時,請注意某些 SQL 方言的差異。這兩個資料庫平台之間也有幾個內建函式不相容或不相容。
基本查詢差異
雖然 Oracle 和 MySQL 適用的 Cloud SQL 都支援 ANSI SQL,但在查詢資料時,兩者仍有幾個基本差異,主要在於系統函式的使用方式。
下表列出 Oracle 和 Cloud SQL for MySQL 的 SELECT
和 FROM
語法差異。
Oracle 功能名稱 | Oracle 實作 | MySQL 適用的 Cloud SQL 支援 | MySQL 適用的 Cloud SQL 等同項目 |
---|---|---|---|
資料擷取的 SQL 基本語法 |
SELECT FROM WHERE GROUP BY HAVING ORDER BY
|
是 |
SELECT FROM WHERE GROUP BY HAVING ORDER BY
|
SELECT
輸出沖印相片 |
SELECT 1 FROM DUAL
|
是 |
SELECT 1 或 SELECT 1 FROM DUAL
|
欄別名 | SELECT COL1 AS C1
|
是 |
SELECT COL1 AS C1 或 SELECT COL1 C1
|
資料表名稱區分大小寫 | 不區分大小寫 (例如,資料表名稱可以是 orders 和 ORDERS ) |
否 | 根據定義的資料表名稱區分大小寫 (例如資料表名稱只能是 orders 或 ORDERS ) |
內嵌檢視畫面
內嵌檢視畫面 (也稱為衍生資料表) 是 SELECT
陳述式,位於 FROM
子句中,用於做為子查詢。內嵌檢視畫面可移除複合計算或排除彙整作業,同時將多個個別查詢濃縮為單一簡易查詢,進而簡化複雜查詢。
以下範例說明從 Oracle 11g/12c 轉換至 Cloud SQL for MySQL 的內嵌檢視畫面。
Oracle 11g/12c 中的內嵌檢視畫面:
SELECT FIRST_NAME,
DEPARTMENT_ID,
SALARY,
DATE_COL
FROM EMPLOYEES,
(SELECT SYSDATE AS DATE_COL FROM DUAL);
在 Cloud SQL for MySQL 5.7 中使用別名建立的有效檢視畫面:
SELECT FIRST_NAME,
DEPARTMENT_ID,
SALARY,
DATE_COL
FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1;
彙整
Cloud SQL for MySQL 支援 Oracle 的彙整類型,但不支援 FULL JOIN
。MySQL 適用的 Cloud SQL 彙整支援使用其他語法,例如 USING
子句、WHERE
子句 (取代 ON
子句),以及 JOIN
陳述式中的 SUBQUERY
。
下表列出 JOIN
轉換範例。
Oracle JOIN 類型 |
MySQL 適用的 Cloud SQL 支援 | MySQL 適用的 Cloud SQL JOIN 語法 |
---|---|---|
INNER JOIN |
是 |
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
|
CROSS JOIN |
是 |
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D
|
FULL JOIN |
否 | 建議您將 UNION 與 LEFT 和 RIGHT JOINS: 搭配使用
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
UNION
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
|
LEFT JOIN
[ OUTER ]
|
是 |
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
|
RIGHT JOIN
[ OUTER ]
|
是 |
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
|
SUBQUERY |
是 |
SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E JOIN (SELECT * FROM DEPARTMENTS)D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
|
雖然 MySQL 適用的 Cloud SQL 支援 UNION
和 UNION ALL
函式,但不支援 Oracle 的 INTERSECT
和 MINUS
函式:
UNION
會在刪除重複記錄後,附加兩個SELECT
陳述式的結果集。UNION ALL
會附加兩個SELECT
陳述式的結果集,但不會刪除重複的記錄。INTERSECT
只會在兩個查詢的結果集中找到記錄時,傳回兩個SELECT
陳述式的交集。MINUS
會比較兩個或多個SELECT
陳述式,只傳回第一個查詢中不包含第二個查詢所傳回的資料列。
下表列出一些 Oracle 到 MySQL 適用的 Cloud SQL 轉換範例。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 支援 | MySQL 適用的 Cloud SQL 等同項目 |
---|---|---|---|
UNION |
SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2
|
是 | SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2
|
UNION ALL |
SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2
|
是 | SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2
|
INTERSECT |
SELECT COL1 FROM TBL1 INTERSECT SELECT COL1 FROM TBL2
|
否 |
SELECT COL1 FROM TBL1 WHERE COL1 IN (SELECT COL1 FROM TBL2)
|
MINUS |
SELECT COL1 FROM TBL1 MINUS SELECT COL1 FROM TBL2
|
否 | SELECT A.COL1
FROM TBL1 A LEFT JOIN TBL2 B
ON USING(COL1)
WHERE B.COL1 IS NULL
|
純量和群組函式
MySQL 適用的 Cloud SQL 提供大量的標量 (單列) 和匯總函式。部分 MySQL 適用的 Cloud SQL 函式與 Oracle 函式相似 (名稱和功能相同,或名稱不同但功能相似)。雖然部分 MySQL 適用的 Cloud SQL 函式名稱與 Oracle 函式相同,但兩者可能會顯示不同的功能。
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 字元函式在名稱和功能上相等的情況,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
CONCAT |
傳回與第二個字串連接的第一個字串:CONCAT('A', 1) = A1
|
是 | CONCAT |
CONCAT('A', 1) = A1 |
CONCAT USING PIPE |
FNAME |' '| LNAME |
否 | CONCAT |
CONCAT(FNAME, ' ', LNAME) |
LOWER 或UPPER |
傳回字串,所有字母皆為小寫或大寫:LOWER('SQL') = sql
|
是 | LOWER 或UPPER |
LOWER('SQL') = sql |
LPAD/RPAD |
傳回 expression1 ,左或右以 expression2 中的字元序列填入,長度為 n 個字元:LPAD('A',3,'*') = **A
|
是 | LPAD 或RPAD |
LPAD('A',3,'*') = **A |
SUBSTR |
傳回字串的一部分,從 x 位置開始 (在本例中為 3),長度為 y 。字串中的第一個位置是 1。
SUBSTR('MySQL', 3, 3)
= SQL
|
是 | SUBSTR |
SUBSTR('MySQL', 3, 3)
= SQL
|
INSTR |
傳回指定字串中字串的位置 (索引):
INSTR('MySQL', 'y')
= 2
|
是 | INSTR |
INSTR('MySQL', 'y')
= 2
|
REPLACE |
傳回字串,其中每個搜尋字串都已替換為替換字串:
REPLACE('ORADB', 'ORA', 'MySQL')
= MySQLDB
|
是 | REPLACE |
REPLACE('ORADB', 'ORA', 'MySQL')
= MySQLDB
|
TRIM |
從字串中裁去開頭或結尾的字元 (或兩者皆裁去):
TRIM(both '-' FROM '-MySQL-')
= MySQL
TRIM(' MySQL ')
= MySQL
|
是 | TRIM |
TRIM(both '-' FROM '-MySQL-')
= MySQL
TRIM(' MySQL ')
= MySQL
|
LTRIM/RTRIM |
從字串的左側或右側移除搜尋結果中出現的所有字元:
LTRIM(' MySQL', ' ')
= MySQL
|
部分支援 | LTRIM or RTRIM |
Oracle LTRIM 和 RTRIM 函式會採用第二個參數,指定要從字串中移除哪些開頭或結尾字元。MySQL 適用的 Cloud SQL 函式只會從指定字串移除開頭和結尾的空白:
LTRIM(' MySQL')
= MySQL
|
ASCII |
接收單一字元並傳回其數字 ASCII 程式碼:ASCII('A') = 65
|
是 | ASCII |
ASCII('A') = 65 |
CHR |
傳回 ASCII 代碼值,這是從 0 到 225 的數值,對應至字元:CHR(65) = A
|
需要不同的函式名稱 | CHAR |
MySQL 適用的 Cloud SQL 會使用 CHAR 函式提供相同功能,因此您需要變更函式名稱:CHAR(65) = A
|
LENGTH |
傳回指定字串的長度:LENGTH('MySQL') = 5
|
是 | LENGTH |
LENGTH('MySQL') = 5 |
REGEXP_REPLACE |
在字串中搜尋規則運算式模式:REGEXP_REPLACE('John', '[hn].', 'e') = Joe
|
否 | 不適用 | 自 MySQL 8 版起提供支援。解決方法是盡可能使用 REPLACE 函式,或將邏輯移至應用程式層。 |
REGEXP_SUBSTR |
透過搜尋字串中的規則運算式模式,擴充 SUBSTR 函式的功能:
REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?')
=
https://console.cloud.google.com/
|
否 | 不適用 | 自 MySQL 8 版起提供支援。解決方法:盡可能使用 SUBSTR 函式,或將邏輯移至應用程式層 |
REGEXP_COUNT |
傳回模式在來源字串中出現的次數 | 否 | 不適用 | 但 MySQL 適用的 Cloud SQL 沒有等同的函式。將此邏輯移至應用程式層。 |
REGEXP_INSTR |
搜尋字串位置 (索引) 的規則運算式模式 | 否 | 不適用 | 自 MySQL 8 版起提供支援。如果是舊版,請將這項邏輯移至應用程式層。 |
REVERSE |
傳回指定字串的反向字串:
REVERSE('MySQL')
= LQSyM
|
是 | REVERSE |
REVERSE('MySQL')
= LQSyM
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 數值函式在名稱和功能上是否相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
ABS |
傳回指定數字的絕對值:ABS(-4.6) = 4.6 |
是 | ABS |
ABS(-4.6) = 4.6 |
CEIL |
傳回大於或等於指定數字的最小整數:CEIL(21.4) = 22 |
是 | CEIL |
CEIL(21.4) = 22 |
FLOOR |
傳回等於或小於指定數字的最大整數:FLOOR(-23.7) = -24
|
是 | FLOOR |
FLOOR(-23.7) = -24 |
MOD |
傳回 m 除以 n 後的餘數:MOD(10, 3) = 1
|
是 | MOD |
MOD(10, 3) = 1 |
ROUND |
傳回 n 四捨五入到小數點右側的整數位數:ROUND(1.39, 1) = 1.4 |
是 | ROUND |
ROUND(1.39, 1) = 1.4 |
TRUNC (數字) |
傳回經截斷至 n2 小數位數的 n1 。第二個參數為選用參數,
TRUNC(99.999) = 99
TRUNC(99.999, 0) = 99
|
需要不同的函式名稱 | TRUNCATE (數字) |
MySQL 適用的 Cloud SQL 函式名稱不同,且第二個參數為必填。TRUNCATE(99.999, 0) = 99
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL datetime
函式在名稱和功能上的對應關係,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
SYSDATE |
傳回資料庫伺服器所在作業系統的目前日期和時間設定:
SELECT SYSDATE
FROM DUAL;
= 31-JUL-2019
|
是 | SYSDATE() |
MySQL 適用的 Cloud SQL
SELECT SYSDATE()
FROM DUAL;
= 2019-01-31 10:01:01.0
您可以在工作階段層級變更 |
SYSTIMESTAMP |
傳回系統日期,包括秒數小數和時區:
SELECT SYSTIMESTAMP FROM DUAL
= 01-JAN-19 07.37.11.622187000 AM +00:00
|
需要不同的函式名稱 |
CURRENT_
TIMESTAMP
|
根據預設,MySQL 適用的 Cloud SQL 函式會傳回不同的 datetime 格式。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
SELECT CURRENT_TIMESTAMP
FROM DUAL;
= 2019-01-31 06:55:07
|
LOCAL_
TIMESTAMP
|
以 TIMESTAMP 類型的形式傳回目前的日期和時間:
SELECT LOCALTIMESTAMP
FROM DUAL
= 01-JAN-19 10.01.10.123456 PM
|
傳回不同的 datetime 格式 |
LOCAL_
TIMESTAMP
|
Cloud SQL for MySQL 函式傳回的 datetime 格式與 Oracle 的預設格式不同。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
SELECT LOCAL_TIMESTAMP
FROM DUAL
= 2019-01-01 10:01:01.0
|
CURRENT_DATE |
傳回目前的日期:
SELECT CURRENT_DATE
FROM DUAL
= 31-JAN-19
|
傳回不同的 datetime 格式 |
CURRENT_
DATE
|
MySQL 適用的 Cloud SQL 函式會傳回不同的 datetime 格式。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
SELECT CURRENT_DATE
FROM DUAL
= 2019-01-31
|
CURRENT_
TIMESTAMP
|
傳回目前的日期和時間:
SELECT CURRENT_TIMESTAMP
FROM DUAL
= 31-JAN-19 06.54.35.543146 AM +00:00
|
傳回不同的 datetime 格式 |
CURRENT_
TIMESTAMP
|
MySQL 適用的 Cloud SQL 函式會傳回不同的 datetime 格式。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
SELECT CURRENT_TIMESTAMP
FROM DUAL
= 2019-01-31 06:55:07
|
ADD_MONTHS |
傳回日期加上整數月:
ADD_MONTHS(SYSDATE, 1)
= 31-JAN-19
|
需要不同的函式名稱 | ADDDATE |
MySQL 適用的 Cloud SQL 函式會傳回不同的 datetime 格式。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
ADDDATE(SYSDATE(), 1)
= 2019-08-01 06:42:49.0
|
EXTRACT (日期部分) |
根據間隔運算式傳回 datetime 欄位的值:
EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
|
是 | EXTRACT (日期部分) |
EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
|
LAST_DAY |
傳回特定日期當月最後一天:
LAST_DAY('01-JAN-2019')
= 31-JAN-19
|
部分支援 | LAST_DAY |
MySQL 適用的 Cloud SQL 函式會傳回與 Oracle 預設格式不同的 datetime 格式。如要重新格式化輸出內容,請使用 DATE_FORMAT() 函式。
LAST_DAY('2019-01-01')
= 2019-01-31
|
MONTH_
BETWEEN
|
傳回指定日期 date1 和 date2 之間的月份數:
MONTHS_BETWEEN(
SYSDATE, SYSDATE-60)
= 1.96
|
部分支援 |
PERIOD_DIFF
|
MySQL 適用的 Cloud SQL PERIOD_DIFF 函式會以整數形式,傳回兩個期間 (格式為 YYMM 或 YYYYMM ) 之間的月份差異:
PERIOD_DIFF(
'201903', '201901')
= 2
|
TO_CHAR (Datetime) |
將數字、datetime 或時間戳記類型轉換為字串類型
TO_CHAR(
SYSDATE,'DD-MM-YYYY HH24:MI:SS')
= 01-01-2019 10:01:01
|
需要不同的函式名稱 | DATE_FORMAT |
MySQL 適用的 Cloud SQL DATE_FORMAT 函式會根據格式字串格式化日期值:
DATE_FORMAT(
SYSDATE(),'%d-%m-%Y %H:%i:%s')
01-01-2019 10:01:01
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 編碼和解碼函式在名稱和功能上是否相同,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
DECODE |
使用 IF-THEN-ELSE 陳述式的功能,逐一將運算式與每個搜尋值進行比較 |
否 | CASE |
使用 MySQL 適用的 Cloud SQL CASE 陳述式來執行類似功能 |
DUMP |
傳回 VARCHAR2 值,其中包含資料類型代碼、長度 (以位元組為單位) 和運算式的內部表示法 |
否 | 不適用 | 不支援 |
ORA_HASH |
計算指定運算式的雜湊值 | 否 | MD5 or SHA |
使用 MD5 函式計算 128 位元總和檢查碼,或使用 SHA 函式計算 160 位元總和檢查碼 |
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 轉換函式在名稱和功能上是否相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
CAST |
將一個內建資料類型或集合型值轉換為另一個內建資料類型或集合型值:
CAST('1' as int) + 1
= 2
|
部分支援 | CAST |
視是否需要明確或隱含轉換而調整:
CAST('1' AS SIGNED) + 1
= 2
|
CONVERT |
將字元字串從一個字元集轉換為另一個字元集:
CONVERT (
'Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1')
= ?? ?? ?? A B C
|
部分支援 | CONVERT |
您需要對 MySQL 適用的 Cloud SQL CONVERT 函式進行一些語法和參數調整:
CONVERT(
'Ä Ê Í A B C ' USING utf8)
= Ä Ê Í A B C
|
TO_CHAR (字串/數字) |
這個函式會將數字或日期轉換為字串:
TO_CHAR(22.73,'$99.9')
= $22.7
|
否 | FORMAT |
MySQL 適用的 Cloud SQL FORMAT 函式會將數字轉換為 #,###,###.## 等格式,並將結果四捨五入為小數位數,然後以字串格式傳回結果:
CONCAT('$',
FORMAT(22.73, 1))
= $22.7
|
TO_DATE |
Oracle 的 TO_DATE 函式會根據 datetimecode 格式將字串轉換為日期:
TO_DATE(
'2019/01/01', 'yyyy-mm-dd')
= 01-JAN-2019
|
需要不同的函式名稱 | STR_TO_DATE |
Cloud SQL for MySQL STR_TO_DATE 函式會接收字串,並根據 datetime 格式傳回日期:
STR_TO_DATE(
'2019/01/01', '%Y/%m/%d')
= 2019-01-01
|
TO_NUMBER |
將運算式轉換為 NUMBER 資料類型的值:
TO_NUMBER('01234')
= 1234
|
需要不同的函式名稱 | CAST |
使用 MySQL 適用的 Cloud SQL CAST 函式,即可傳回與 Oracle TO_NUMBER 函式相同的結果:
CAST('01234' as SIGNED)
= 1234
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 的條件 SELECT
函式在名稱和功能上相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
CASE |
CASE 陳述式會從一連串條件中選擇,並使用以下語法執行對應的陳述式:
CASE WHEN condition THEN result
[WHEN ...] [ELSE result]
END
|
是 | CASE |
除了 CASE 函式之外,Cloud SQL for MySQL 也支援在 SELECT 陳述式中使用 IF/ELSE 條件處理:
CASE WHEN condition THEN result
[WHEN ...] [ELSE result]
END
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 空值函式在名稱和功能上是否相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
COALESCE |
傳回運算式清單中的第一個非空值運算式:
COALESCE(
null, '1', 'a')
= a
|
是 | COALESCE |
COALESCE(
null, '1', 'a')
= 1
|
NULLIF |
比較 expression1 和 expression2 。如果兩者相等,函式會傳回 null 。如果不相等,函式會傳回 expression1 :
NULLIF('1', '2')
= a
|
是 | NULLIF |
NULLIF('1', '2')
= a
|
NVL |
在查詢結果中,將 null 值替換為字串:
NVL(null, 'a')
= a
|
否 | IFNULL |
IFNULL(null, 'a')
= a
|
NVL2 |
根據運算式是否為空值,判斷查詢傳回的值 | 否 | CASE |
CASE 陳述式會從一系列條件中選擇,並執行相應的陳述式:
CASE WHEN condition THEN result
[WHEN ...] [ELSE result]
END
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 環境和 ID 函式在名稱和功能上是否相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
SYS_GUID |
產生並傳回由 16 個位元組組成的全域專屬 ID (RAW 值):
SELECT SYS_GUID()
FROM DUAL
=
8EFA4A31468B4C6DE05011AC0200009E
|
否 | REPLACE 和 UUID |
解決方法是使用 REPLACE 和 UUID 函式模擬 SYS_GUID 函式:
REPLACE(
UUID(), '-', '')
|
UID |
傳回可唯一識別工作階段使用者 (已登入的使用者) 的整數:
SELECT UID FROM DUAL
= 43
|
否 | 不適用 | 不適用 |
USER |
傳回已連線至目前工作階段的使用者使用者名稱:
SELECT USER FROM DUAL
= username
|
是 | USER + INSTR + SUBSTR |
MySQL 適用的 Cloud SQL USER 函式會傳回連線的使用者名稱和主機名稱 (root@IP_ADDRESS )。如要只擷取使用者名稱,請使用其他支援函式:
SELECT
SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL
= root
|
USERENV |
傳回目前 Oracle 工作階段的相關資訊,例如工作階段的語言:
SELECT USERENV('LANGUAGE')
FROM DUAL
= ENGLISH_AMERICA.
AL32UTF8
|
否 |
SHOW SESSION
VARIABLES
|
MySQL 適用的 Cloud SQL SHOW SESSION VARIABLES 陳述式會傳回目前工作階段的設定:
SHOW SESSION VARIABLES LIKE '%collation%';
= utf8_general_ci
|
ROWID |
Oracle 會為資料表的每個資料列指派專屬的 ROWID ,用於識別資料表中的資料列。ROWID 是資料行位址,其中包含資料物件編號、資料列的資料區塊、資料列位置和資料檔案。 |
部分支援 | 不適用 |
ROW_NUMBER() 可從 MySQL 8.0 開始使用。如果您使用的是舊版,請使用工作階段變數 @row_number 模擬相同功能。 |
ROWNUM |
傳回數字,代表 Oracle 資料表傳回資料列的順序 | 部分支援 | 不適用 | ROW_NUMBER() 自 MySQL 8.0 起提供。如果您使用的是舊版,請使用工作階段變數 @row_number 模擬相同功能。 |
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 的匯總 (群組) 函式在名稱和功能上相等的情況,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
AVG |
傳回資料欄或運算式的平均值 | 是 | AVG |
等同於 Oracle |
COUNT
|
傳回查詢傳回的資料列數 | 是 | COUNT |
等同於 Oracle |
COUNT
(DISTINCT)
|
傳回資料欄或運算式中不重複值的數量 | 是 |
COUNT
(DISTINCT)
|
等同於 Oracle |
MAX |
傳回資料欄或運算式的最大值 | 是 | 等同於 Oracle | |
MIN |
傳回資料欄或運算式的最小值 | 是 | MIN |
等同於 Oracle |
SUM |
傳回資料欄或運算式的值總和 | 是 | SUM |
等同於 Oracle |
LISTAGG |
將 ORDER BY 子句中指定的每個群組內資料排序,並連結計量欄的值:
SELECT LISTAGG(
DEPARTMENT_NAME, ', ')
WITHIN GROUP
(ORDER BY DEPARTMENT_NAME) DEPT
FROM DEPARTMENTS;
-- Single line results
= Accounting, Administration, Benefits, Construction
|
需要不同的函式名稱和語法 |
GROUP_
CONCAT
|
使用 MySQL 適用的 Cloud SQL GROUP_CONCAT 函式,即可傳回等效結果:
SELECT GROUP_CONCAT(
DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT
FROM DEPARTMENTS;
-- Single line results
= Accounting, Administration, Benefits, Construction
|
下表說明 Oracle 和 MySQL 適用的 Cloud SQL FETCH
函式在名稱和功能上的對應關係。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 | MySQL 適用的 Cloud SQL 導入作業 |
---|---|---|---|---|
FETCH |
從多列查詢的結果集擷取指定數量的資料列:
SELECT * FROM
EMPLOYEES
FETCH FIRST 10 ROWS ONLY;
|
是 | LIMIT |
使用 MySQL LIMIT 子句,從查詢中擷取資料列:
SELECT * FROM
EMPLOYEES
LIMIT 10;
|
基本篩選、運算子和子查詢
基本篩選、運算子函式和子查詢的轉換作業相對簡單,只需花費少許心力即可完成。由於 Oracle 和 MySQL 適用的 Cloud SQL 使用不同的預設日期格式,因此大部分的努力都集中在轉換日期格式:
- Oracle
SYSDATE
函式預設會傳回以下格式:01-AUG-19
。 - 預設情況下,MySQL 適用的 Cloud SQL
SYSDATE()
函式會傳回以下格式:2019-08-01 12:04:05
。
如要設定日期和時間格式,請使用 MySQL DATE_FORMAT
或 STR_TO_DATE
函式。
下表說明 Oracle 和 MySQL 適用的 Cloud SQL 基本篩選、運算子和子查詢函式的名稱和功能相等,以及建議轉換的情況。
Oracle 函式 | Oracle 實作 | MySQL 適用的 Cloud SQL 等同項目 | MySQL 適用的 Cloud SQL 函式 |
---|---|---|---|
EXISTS/
NOT EXISTS
|
是 |
EXISTS/
NOT EXISTS
|
SELECT * FROM DEPARTMENTS D
WHERE EXISTS (SELECT 1
FROM EMPLOYEES E
WHERE
E.DEPARTMENT_ID =
D.DEPARTMENT_ID);
|
IN/NOT IN |
是 | IN/NOT IN |
SELECT * FROM DEPARTMENTS D
WHERE DEPARTMENT_ID IN
(SELECT DEPARTMENT_ID
FROM EMPLOYEES E);
-- OR
SELECT * FROM EMPLOYEES
WHERE (EMPLOYEE_ID, DEPARTMENT_ID)
IN((100, 90));
|
LIKE/NOT LIKE |
是 | LIKE/NOT LIKE |
SELECT * FROM EMPLOYEES
WHERE FIRST_NAME LIKE '_e_n%';
|
BETWEEN/
NOT BETWEEN
|
是 |
BETWEEN/
NOT BETWEEN
|
SELECT * FROM EMPLOYEES
WHERE EXTRACT(YEAR FROM HIRE_DATE)
NOT BETWEEN 2001 and 2004;
|
AND/OR |
是 | AND/OR |
SELECT * FROM EMPLOYEES
WHERE DEPARTMENT_ID IN(100, 101)
AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05');
|
SubQuery |
是 | SubQuery |
MySQL 適用的 Cloud SQL 支援 SELECT 子句、JOIN 子句中的子查詢,以及 WHERE/AND 子句中的篩選:
-- SELECT Subquery
SELECT D.DEPARTMENT_NAME,
(SELECT AVG(SALARY) AS AVG_SAL
FROM EMPLOYEES E
WHERE E.DEPARTMENT_ID =
D.DEPARTMENT_ID) AVG_SAL
FROM DEPARTMENTS D;
-- JOIN Subquery
SELECT FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEES E JOIN
(SELECT *
FROM DEPARTMENTS
WHERE LOCATION_ID = 2700) D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
-- Filtering Subquery
SELECT FIRST_NAME,
LAST_NAME,
SALARY
FROM EMPLOYEES
WHERE SALARY < (SELECT AVG(SALARY)
FROM EMPLOYEES);
|
運算子 | 是 | 運算子 | MySQL 適用的 Cloud SQL 支援所有基本運算子:> | >= | < | <= | = | <> | !=
|
針對 MySQL 適用的 Cloud SQL 查詢的最佳做法
為維持 MySQL 適用的 Cloud SQL 與 Oracle 之間的效能水準,您可能需要對查詢進行最佳化。這些最佳化措施包括變更索引結構和調整資料庫結構定義。本節提供幾項指南,協助您在 MySQL 適用的 Cloud SQL 上獲得類似的查詢效能。
建立叢集索引
使用 InnoDB 儲存引擎時,最佳做法是定義具有主鍵的資料表,因為這個鍵會在該資料表上建立叢集索引。除了改善查詢效能之外,這個方法還可讓您建立其他次要索引。不過,請避免建立過多索引。建立多個索引並不會提升效能,反而可能會減緩 DML 的執行速度。這項最佳做法會引導您採用第二項最佳做法:定期監控是否有重複的索引,如果有,請從資料庫中刪除。
使用以下查詢,找出沒有主鍵的資料表,以便為這些資料表建立主鍵:
mysql> SELECT t.table_schema, t.table_name
FROM information_schema.tables t LEFT JOIN
information_schema.statistics s
ON t.table_schema=s.table_schema AND t.table_name=s.table_name
AND s.non_unique=0
WHERE s.table_name IS NULL
AND t.table_schema NOT IN('sys', 'information_schema', 'mysql',
'performance_schema')
AND t.`TABLE_TYPE` <> 'VIEW';
使用以下查詢找出沒有索引的資料表,以便為這些資料表建立索引:
mysql> SELECT t.table_schema, t.table_name FROM INFORMATION_SCHEMA.tables t
WHERE table_name NOT IN
(SELECT table_name FROM (
SELECT table_name, index_name
FROM information_schema.statistics
GROUP BY table_name, index_name) tab_ind_cols
GROUP BY table_name)
AND table_schema NOT IN('sys', 'information_schema', 'mysql', 'performance_schema')
AND TABLE_TYPE <> 'VIEW';
請使用以下查詢檢查是否有重複的索引,以便移除重複項目:
mysql> SELECT * FROM sys.schema_redundant_indexes;
調整查詢參數
如要調整查詢效能,您可能需要調整工作階段參數。MySQL 適用的 Cloud SQL 提供一組旗標,可供您用於這項用途,包括下列旗標:
- InnoDB 相關參數
SORT
個參數JOIN
個參數- 快取處理參數
監控查詢
執行速度緩慢的查詢可能會導致系統停止回應或導致其他瓶頸,因此請務必定期監控查詢。
您可以透過以下幾種方式診斷執行速度緩慢的 SQL 陳述式:
- 使用 MySQL 適用的 Cloud SQL 資訊主頁,取得執行速度緩慢的查詢相關的即時和歷來洞察資料。
- 使用 Cloud Monitoring 監控 MySQL 適用的 Cloud SQL 慢速查詢記錄。
使用 MySQL 適用的 Cloud SQL
statement_analysis
檢視畫面,查看 SQL 陳述式的執行階段統計資料:mysql> SELECT * FROM sys.statement_analysis;
分析 MySQL 適用的 Cloud SQL 查詢
Cloud SQL for MySQL 中的查詢最佳化工具會為 SELECT
、INSERT
、UPDATE
和 DELETE
陳述式產生執行計畫。當您調整執行速度緩慢的查詢時,這些計畫就很實用。請注意以下幾點:
- 執行計畫並非需要遷移的資料庫物件,而是用於分析 Oracle 和 MySQL 適用的 Cloud SQL 之間,在相同資料集上執行相同陳述式的效能差異。
- MySQL 適用的 Cloud SQL 不支援與 Oracle 相同的執行計畫語法、功能或輸出內容。
以下是說明 Oracle 執行計畫和 MySQL 適用的 Cloud SQL 執行計畫差異的示例計畫:
SQL> EXPLAIN PLAN FOR
SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105;
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY (FORMAT=>'ALL +OUTLINE'));
Plan hash value: 1833546154
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 69 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 69 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
mysql> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105;
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | EMPLOYEES | NULL | const | PRIMARY | PRIMARY | 3 | const | 1 | 100.00 | NULL |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
最佳化內儲程序和觸發條件
與 Oracle 相反,MySQL 適用的 Cloud SQL 會在每次執行時剖析儲存的程序和函式。MySQL BENCHMARK()
公用程式是一項實用的工具,可用於基準化儲存程序和函式效能。這項工具會採用兩個參數 (一個為迭代計數,另一個為運算式),並估算指定運算式的執行時間 (例如儲存程序、函式和 SELECT
陳述式)。輸出內容代表所有疊代作業的總執行時間。
以下範例說明 BENCHMARK()
公用程式:
-- SELECT Expression Example
mysql> select benchmark(10000000, 'select sysdate()');
+-----------------------------------------+
| benchmark(10000000, 'select sysdate()') |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
1 row in set (0.12 sec)
-- Result: Run time of 0.12 sec for 1,0000,000 iterations
-- FUNCTION Example
mysql> select benchmark(1000000, func1());
+-----------------------------+
| benchmark(1000000, func1()) |
+-----------------------------+
| 0 |
+-----------------------------+
1 row in set (2.54 sec)
-- Result: Run time of 2.54 sec for 1,000,000 iterations
如果您在轉換期間發現效能下降,請使用 MySQL EXPLAIN
指令找出導致效能下降的可能因素。針對效能緩慢問題的常見解決方案,就是變更資料表索引結構,以便配合 MySQL 最佳化工具。另一個常見做法是減少不必要的資料擷取,或在 MySQL 程序碼中使用暫時性資料表,以便最佳化轉換的 PL/SQL 程式碼。