將甲骨文轉換為亞馬遜 RDS 的 MySQL 或亞馬遜極光 MySQL - AWS Schema Conversion Tool

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

將甲骨文轉換為亞馬遜 RDS 的 MySQL 或亞馬遜極光 MySQL

要在轉換後的 MySQL 代碼中模擬甲骨文數據庫函數,請使用甲骨文到 MySQL 擴展包。AWS SCT如需擴充功能套件的詳細資訊,請參閱使用 AWS SCT 擴充套件

將 MySQL 作為目標資料庫的權限

MySQL 作為目標所需的權限如下:

  • 建立於 * 。 *

  • 更改 * 。 *

  • 下降 * 。 *

  • 索引 * 。 *

  • 參考文獻 * 。 *

  • SELECT ON *.*

  • 在 * 上建立檢視 。 *

  • SHOW VIEW ON *.*

  • 觸發器於 * 。 *

  • 在 * 上創建例程 。 *

  • 改變例程 * 。 *

  • 執行於 * 。 *

  • 在 * 上創建臨時表 。 *

  • AW_LAMBDA 訪問

  • 插入,在 AWS_ORACLE_EXT 上進行更新。 *

  • 插入、更新、刪除 *

如果您使用 MySQL 資料庫版本 5.7 或更低版本做為目標,請授與叫用 LAMBDA *.* 權限,而非 AWS_LAMBDA 存取權限。對於 MySQL 資料庫 8.0 版及更高版本,請授予 AW_LAMBDA 存取權限。

您可以使用下列程式碼範例來建立資料庫使用者並授與權限。

CREATE USER 'user_name' IDENTIFIED BY 'your_password'; GRANT CREATE ON *.* TO 'user_name'; GRANT ALTER ON *.* TO 'user_name'; GRANT DROP ON *.* TO 'user_name'; GRANT INDEX ON *.* TO 'user_name'; GRANT REFERENCES ON *.* TO 'user_name'; GRANT SELECT ON *.* TO 'user_name'; GRANT CREATE VIEW ON *.* TO 'user_name'; GRANT SHOW VIEW ON *.* TO 'user_name'; GRANT TRIGGER ON *.* TO 'user_name'; GRANT CREATE ROUTINE ON *.* TO 'user_name'; GRANT ALTER ROUTINE ON *.* TO 'user_name'; GRANT EXECUTE ON *.* TO 'user_name'; GRANT CREATE TEMPORARY TABLES ON *.* TO 'user_name'; GRANT AWS_LAMBDA_ACCESS TO 'user_name'; GRANT INSERT, UPDATE ON AWS_ORACLE_EXT.* TO 'user_name'; GRANT INSERT, UPDATE, DELETE ON AWS_ORACLE_EXT_DATA.* TO 'user_name';

在上述範例中,將 user_name 取代為您的使用者名稱。然後,用安全的密碼替換您的密碼

如果您使用 MySQL 資料庫版本 5.7 或更低版本作為目標,請使用GRANT INVOKE LAMBDA ON *.* TO 'user_name'代替GRANT AWS_LAMBDA_ACCESS TO 'user_name'.

若要使用適用於 MySQL 的亞馬遜 RDS 或極光 MySQL 作為目標,請將lower_case_table_names參數設定為1。此值意味著 MySQL 服務器處理不區分大小寫的表,索引,觸發器和數據庫等對象名稱的標識符。如果您已在目標執行個體中開啟二進位記錄功能,請將log_bin_trust_function_creators參數設定為1。在這種情況下,您不需要使用DETERMINISTICREADS SQL DATANO SQL特性來建立已儲存的函數。若要設定這些參數,請建立新的資料庫參數群組或修改現有的資料庫參數群組。

甲骨文到 MySQL 的轉換設置

若要編輯 Oracle 到 MySQL 的轉換設定,請在中選擇 [設定]AWS SCT,然後選擇 [轉換設定]。從上面的列表中,選擇甲骨文,然後選擇甲骨文-MySQL。 AWS SCT顯示甲骨文到 MySQL 的轉換的所有可用設置。

甲骨文到 MySQL 的轉換設置AWS SCT包括以下選項:

  • 用於限制轉換後代碼中行動項目的註釋數量。

    針對所選嚴重性及更高之行動項目的已轉換程式碼中新增註解,請選擇行動項目的嚴重性。 AWS SCT在已轉換的程式碼中加入所選嚴重性及更高嚴重性之行動項目的註解。

    例如,若要將轉換後的程式碼中的註解數目降到最低,請選擇「僅限錯誤」。若要在轉換的程式碼中包含所有行動項目的註解,請選擇 [所有郵件]。

  • 為了解決您的源 Oracle 數據庫可以使用ROWID偽列,但 MySQL 不支持類似的功能。 AWS SCT可以模擬轉換後的ROWID代碼中的偽列。要這樣做,請選擇生成為生成行 ID 的標識

    如果您的源 Oracle 代碼不使用ROWID偽列,請選擇不生成為生成 ID? 在這種情況下,轉換後的代碼的工作速度更快。

  • 在原始程式碼 Oracle 程式碼包含TO_CHARTO_DATE、和TO_NUMBER函數時使用 MySQL 不支援的參數。默認情況下,AWS SCT模擬這些參數在轉換後的代碼的使用。

    當您的原始程式碼只包含 PostgreSQL 支援的參數時,您可以使用原生 MySQL TO_CHARTO_NUMBER函數。TO_DATE在這種情況下,轉換後的代碼的工作速度更快。若只要包括這些參數,請選取下列值:

    • 函數 TO_CHAR () 不使用甲骨文特定的格式化字符串

    • 函數 TO_DATE () 不使用甲骨文特定的格式化字符串

    • 函數 TO_NUMBER () 不使用甲骨文特定的格式化字符串

  • 為了補充您的數據庫和應用程序是否在不同的時區中運行。默認情況下,AWS SCT模擬轉換後的代碼中的時區。但是,當您的資料庫和應用程式使用相同的時區時,就不需要此模擬。在此情況下,請選取用戶端上的「時區」與伺服器上的時區相符。

移轉考量

當您將 Oracle 轉換為適用於 MySQL 的 RDS 或極光 MySQL 時,若要變更陳述式執行的順序,您可以使用GOTO陳述式和標籤。系統會略過敘述句後面的任何 PL/SQL 敘述句,並在標籤處繼續處理。GOTO您可以在程序、批次或GOTO陳述式區塊中的任何位置使用陳述式和標籤。您也可以接下來 GOTO 語句。

MySQL 不使用GOTO語句。當AWS SCT轉換包含GOTO陳述式的程式碼時,會將陳述式轉換為使用 BEGIN…END or LOOP…END LOOP 陳述式。

您可以在下表中找到如何AWS SCT轉換GOTO陳述式的範例。

Oracle 陳述式 MySQL 陳述式
BEGIN .... statement1; .... GOTO label1; statement2; .... label1: Statement3; .... END
BEGIN label1: BEGIN .... statement1; .... LEAVE label1; statement2; .... END; Statement3; .... END
BEGIN .... statement1; .... label1: statement2; .... GOTO label1; statement3; .... statement4; .... END
BEGIN .... statement1; .... label1: LOOP statement2; .... ITERATE label1; LEAVE label1; END LOOP; statement3; .... statement4; .... END
BEGIN .... statement1; .... label1: statement2; .... statement3; .... statement4; .... END
BEGIN .... statement1; .... label1: BEGIN statement2; .... statement3; .... statement4; .... END; END

轉換與語句甲骨文到 RDS 為 MySQL 或亞馬遜極光 MySQL

您可以使用 Oracle 的 WITH 子句 (subquery_factoring) 對子查詢區塊指派名稱 (query_name)。接著,您即可透過指定 query_name 在查詢中的多處位置參考該子查詢區塊。如果子查詢塊不包含鏈接或參數(本地,過程,函數,包),則AWS SCT將子句轉換為視圖或臨時表。

將子句轉換為暫時資料表的優點是,對子查詢的重複引用可能會更有效率。效率更高的是因為資料很容易從暫時資料表中檢索,而不是每個引用都需要。您可以通過使用其他視圖或臨時表來模擬這一點。視圖名稱會使用格式 <procedure_name>$<subselect_alias>

您可以在下表中找到範例。

Oracle 陳述式 MySQL 陳述式
CREATE PROCEDURE TEST_ORA_PG.P_WITH_SELECT_VARIABLE_01 (p_state IN NUMBER) AS l_dept_id NUMBER := 1; BEGIN FOR cur IN (WITH dept_empl(id, name, surname, lastname, state, dept_id) AS ( SELECT id, name, surname, lastname, state, dept_id FROM test_ora_pg.dept_employees WHERE state = p_state AND dept_id = l_dept_id) SELECT id,state FROM dept_empl ORDER BY id) LOOP NULL; END LOOP;
CREATE PROCEDURE test_ora_pg.P_WITH_SELECT_VARIABLE_01(IN par_P_STATE DOUBLE) BEGIN DECLARE var_l_dept_id DOUBLE DEFAULT 1; DECLARE var$id VARCHAR (8000); DECLARE var$state VARCHAR (8000); DECLARE done INT DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT ID, STATE FROM (SELECT ID, NAME, SURNAME, LASTNAME, STATE, DEPT_ID FROM TEST_ORA_PG.DEPT_EMPLOYEES WHERE STATE = par_p_state AND DEPT_ID = var_l_dept_id) AS dept_empl ORDER BY ID; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE; OPEN cur; read_label: LOOP FETCH cur INTO var$id, var$state; IF done THEN LEAVE read_label; END IF; BEGIN END; END LOOP; CLOSE cur; END;
CREATE PROCEDURE TEST_ORA_PG.P_WITH_SELECT_REGULAR_MULT_01 AS BEGIN FOR cur IN ( WITH dept_empl AS ( SELECT id, name, surname, lastname, state, dept_id FROM test_ora_pg.dept_employees WHERE state = 1), dept AS (SELECT id deptid, parent_id, name deptname FROM test_ora_pg.department ) SELECT dept_empl.*,dept.* FROM dept_empl, dept WHERE dept_empl.dept_id = dept.deptid ) LOOP NULL; END LOOP;
CREATE VIEW TEST_ORA_PG.`P_WITH_SELECT_REGULAR_MULT_01$dept_empl `(id, name, surname, lastname, state, dept_id) AS (SELECT id, name, surname, lastname, state, dept_id FROM test_ora_pg.dept_employees WHERE state = 1); CREATE VIEW TEST_ORA_PG.`P_WITH_SELECT_REGULAR_MULT_01$dept `(deptid, parent_id,deptname) AS (SELECT id deptid, parent_id, name deptname FROM test_ora_pg.department); CREATE PROCEDURE test_ora_pg.P_WITH_SELECT_REGULAR_MULT_01() BEGIN DECLARE var$ID DOUBLE; DECLARE var$NAME VARCHAR (30); DECLARE var$SURNAME VARCHAR (30); DECLARE var$LASTNAME VARCHAR (30); DECLARE var$STATE DOUBLE; DECLARE var$DEPT_ID DOUBLE; DECLARE var$deptid DOUBLE; DECLARE var$PARENT_ID DOUBLE; DECLARE var$deptname VARCHAR (200); DECLARE done INT DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT dept_empl.*, dept.* FROM TEST_ORA_PG.`P_WITH_SELECT_REGULAR_MULT_01$dept_empl ` AS dept_empl, TEST_ORA_PG.`P_WITH_SELECT_REGULAR_MULT_01$dept ` AS dept WHERE dept_empl.DEPT_ID = dept.DEPTID; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE; OPEN cur; read_label: LOOP FETCH cur INTO var$ID, var$NAME, var$SURNAME, var$LASTNAME, var$STATE, var$DEPT_ID, var$deptid, var$PARENT_ID, var$deptname; IF done THEN LEAVE read_label; END IF; BEGIN END; END LOOP; CLOSE cur; END; call test_ora_pg.P_WITH_SELECT_REGULAR_MULT_01()
CREATE PROCEDURE TEST_ORA_PG.P_WITH_SELECT_VAR_CROSS_02(p_state IN NUMBER) AS l_dept_id NUMBER := 10; BEGIN FOR cur IN ( WITH emp AS (SELECT id, name, surname, lastname, state, dept_id FROM test_ora_pg.dept_employees WHERE dept_id > 10 ), active_emp AS ( SELECT id FROM emp WHERE emp.state = p_state ) SELECT * FROM active_emp ) LOOP NULL; END LOOP; END;
CREATE VIEW TEST_ORA_PG.`P_WITH_SELECT_VAR_CROSS_01$emp `(id, name, surname, lastname, state, dept_id) AS (SELECT id, name, surname, lastname, state, dept_id FROM TEST_ORA_PG.DEPT_EMPLOYEES WHERE DEPT_ID > 10); CREATE PROCEDURE test_ora_pg.P_WITH_SELECT_VAR_CROSS_02(IN par_P_STATE DOUBLE) BEGIN DECLARE var_l_dept_id DOUBLE DEFAULT 10; DECLARE var$ID DOUBLE; DECLARE done INT DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT * FROM (SELECT ID FROM TEST_ORA_PG. `P_WITH_SELECT_VAR_CROSS_01$emp` AS emp WHERE emp.STATE = par_p_state) AS active_emp; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE; OPEN cur; read_label: LOOP FETCH cur INTO var$ID; IF done THEN LEAVE read_label; END IF; BEGIN END; END LOOP; CLOSE cur; END;