GoldenGate教程FG048-SQL语言与开发
本文档是GoldenGate数据库培训系列的第048篇,主要介绍SQL语言与GoldenGate的关系,包括SQL基础操作、GoldenGate相关的SQL语句、数据转换与处理、SQL性能优化等内容,以及相关的实战案例和经验分享。
Part01-基础概念与理论知识
1.1 SQL基础概念
SQL(Structured Query Language)是一种用于管理关系型数据库的标准语言,包括以下核心概念:
- DDL(数据定义语言):用于定义数据库结构,如CREATE、ALTER、DROP等语句
- DML(数据操作语言):用于操作数据,如INSERT、UPDATE、DELETE等语句
- DCL(数据控制语言):用于控制数据访问权限,如GRANT、REVOKE等语句
- TCL(事务控制语言):用于控制事务,如COMMIT、ROLLBACK等语句
- 查询语句:用于查询数据,如SELECT语句
- 数据查询:从数据库中检索数据
- 数据插入:向数据库中添加新数据
- 数据更新:修改数据库中的现有数据
- 数据删除:从数据库中删除数据
- 数据定义:创建和修改数据库结构
- 数据控制:管理用户访问权限
1.2 GoldenGate与SQL的关系
GoldenGate与SQL的关系主要体现在以下几个方面:
- 数据捕获:GoldenGate通过解析数据库的重做日志或归档日志来捕获SQL操作
- 数据应用:GoldenGate将捕获的SQL操作应用到目标数据库
- 数据转换:GoldenGate可以在数据同步过程中对SQL进行转换和处理
- 配置管理:GoldenGate的配置文件中包含SQL相关的设置和参数
- 监控和管理:通过SQL语句可以监控GoldenGate的运行状态
Part02-生产环境规划与建议
2.1 SQL开发规划
在GoldenGate项目中,SQL开发规划需要考虑以下因素:
## 1. 数据模型设计
– **表结构设计:** 合理设计表结构,考虑数据类型、索引、约束等
– **关系设计:** 设计合理的表关系,确保数据完整性
– **分区设计:** 根据数据量和查询模式,设计合理的分区策略
## 2. SQL语句规划
– **查询语句:** 优化查询语句,提高查询性能
– **DML语句:** 合理使用DML语句,确保数据一致性
– **DDL语句:** 规划DDL语句的执行时机,避免影响GoldenGate同步
## 3. 数据转换规划
– **数据类型转换:** 规划源端和目标端的数据类型映射
– **业务逻辑转换:** 规划数据同步过程中的业务逻辑转换
– **数据过滤:** 规划需要过滤的数据和条件
## 4. 性能规划
– **索引设计:** 合理设计索引,提高查询性能
– **SQL优化:** 优化SQL语句,减少执行时间
– **批量操作:** 合理使用批量操作,提高数据处理效率
## 5. 安全性规划
– **权限管理:** 合理设置用户权限,确保数据安全
– **数据加密:** 考虑敏感数据的加密处理
– **审计日志:** 记录重要的SQL操作,便于审计
2.2 SQL开发建议
基于实际经验,以下是SQL开发的建议:
- 遵循SQL标准:使用标准SQL语句,提高代码的可移植性
- 使用参数化查询:避免SQL注入攻击,提高性能
- 优化查询语句:使用EXPLAIN计划分析查询性能,优化执行计划
- 合理使用索引:根据查询模式设计合适的索引,避免过度索引
- 批量操作:对于大量数据操作,使用批量插入、更新等操作
- 事务管理:合理使用事务,确保数据一致性
- 错误处理:添加适当的错误处理,提高代码的健壮性
- 代码规范:遵循SQL代码规范,提高代码的可读性和可维护性
Part03-生产环境项目实施方案
3.1 基础SQL操作
基础SQL操作包括查询、插入、更新、删除等基本操作:
## 1. 查询操作
– **基本查询:**
“`sql
SELECT * FROM fgedu.employees;
SELECT employee_id, first_name, last_name FROM fgedu.employees WHERE department_id = 10;
“`
– **聚合查询:**
“`sql
SELECT department_id, COUNT(*) AS employee_count FROM fgedu.employees GROUP BY department_id;
SELECT AVG(salary) AS avg_salary FROM fgedu.employees WHERE department_id = 10;
“`
– **连接查询:**
“`sql
SELECT e.employee_id, e.first_name, d.department_name
FROM fgedu.employees e
JOIN fgedu.departments d ON e.department_id = d.department_id;
“`
## 2. 插入操作
– **单行插入:**
“`sql
INSERT INTO fgedu.employees (employee_id, first_name, last_name, email, hire_date, job_id, salary, department_id)
VALUES (1001, ‘John’, ‘Doe’, ‘john.doe@example.com’, SYSDATE, ‘IT_PROG’, 5000, 10);
“`
– **多行插入:**
“`sql
INSERT INTO fgedu.employees (employee_id, first_name, last_name, email, hire_date, job_id, salary, department_id)
VALUES
(1002, ‘Jane’, ‘Smith’, ‘jane.smith@example.com’, SYSDATE, ‘IT_PROG’, 5500, 10),
(1003, ‘Mike’, ‘Johnson’, ‘mike.johnson@example.com’, SYSDATE, ‘IT_PROG’, 6000, 10);
“`
– **从其他表插入:**
“`sql
INSERT INTO fgedu.employees_backup (employee_id, first_name, last_name, email)
SELECT employee_id, first_name, last_name, email FROM fgedu.employees WHERE department_id = 10;
“`
## 3. 更新操作
– **基本更新:**
“`sql
UPDATE fgedu.employees SET salary = salary * 1.1 WHERE department_id = 10;
“`
– **条件更新:**
“`sql
UPDATE fgedu.employees SET salary = 6000 WHERE employee_id = 1001 AND salary < 5500;
```
- **多表更新:**
```sql
UPDATE fgedu.employees e
SET e.salary = e.salary * 1.05
WHERE EXISTS (SELECT 1 FROM fgedu.departments d WHERE e.department_id = d.department_id AND d.department_name = 'IT');
```
## 4. 删除操作
- **基本删除:**
```sql
DELETE FROM fgedu.employees WHERE employee_id = 1001;
```
- **条件删除:**
```sql
DELETE FROM fgedu.employees WHERE hire_date < SYSDATE - 365;
```
- **截断表:**
```sql
TRUNCATE TABLE fgedu.employees_backup;
```
3.2 GoldenGate相关SQL
GoldenGate相关的SQL语句包括数据库配置、权限管理、监控等操作:
## 1. 数据库配置SQL
– **启用归档模式:**
“`sql
ALTER DATABASE ARCHIVELOG;
“`
– **启用强制日志:**
“`sql
ALTER DATABASE FORCE LOGGING;
“`
– **启用补充日志:**
“`sql
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER TABLE fgedu.employees ADD SUPPLEMENTAL LOG GROUP emp_pk (employee_id) ALWAYS;
“`
## 2. 权限管理SQL
– **创建GoldenGate用户:**
“`sql
CREATE USER ggadmin IDENTIFIED BY ggadmin123;
“`
– **授予权限:**
“`sql
GRANT CONNECT, RESOURCE TO ggadmin;
GRANT SELECT ANY TABLE TO ggadmin;
GRANT INSERT, UPDATE, DELETE ON fgedu.* TO ggadmin;
GRANT EXECUTE ON dbms_logmnr TO ggadmin;
GRANT EXECUTE ON dbms_logmnr_d TO ggadmin;
GRANT SELECT ON v_$database TO ggadmin;
GRANT SELECT ON v_$log TO ggadmin;
GRANT SELECT ON v_$logfile TO ggadmin;
GRANT SELECT ON v_$archived_log TO ggadmin;
GRANT SELECT ON v_$transaction TO ggadmin;
GRANT SELECT ON v_$session TO ggadmin;
GRANT SELECT ON v_$instance TO ggadmin;
“`
## 3. 监控SQL
– **查询GoldenGate相关表:**
“`sql
SELECT * FROM ggadmin.gg_trail;
SELECT * FROM ggadmin.gg_process;
“`
– **查询数据库状态:**
“`sql
SELECT log_mode, force_logging FROM v$database;
SELECT supplemental_log_data_min FROM v$database;
“`
– **查询表补充日志状态:**
“`sql
SELECT owner, table_name, supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_all
FROM dba_tab_modifications
WHERE table_name = ‘EMPLOYEES’;
“`
## 4. 数据验证SQL
– **比较源端和目标端数据:**
“`sql
— 源端
SELECT COUNT(*) FROM source.employees;
SELECT SUM(salary) FROM source.employees;
— 目标端
SELECT COUNT(*) FROM target.employees;
SELECT SUM(salary) FROM target.employees;
“`
– **检查数据一致性:**
“`sql
SELECT s.employee_id, s.first_name, s.last_name, s.salary,
t.employee_id, t.first_name, t.last_name, t.salary
FROM source.employees s
FULL OUTER JOIN target.employees t ON s.employee_id = t.employee_id
WHERE s.employee_id IS NULL OR t.employee_id IS NULL
OR s.first_name != t.first_name
OR s.last_name != t.last_name
OR s.salary != t.salary;
“`
3.3 数据转换与处理
GoldenGate支持在数据同步过程中进行数据转换和处理:
## 1. GoldenGate数据转换
– **列映射:**
“`
MAP source.employees, TARGET target.employees,
COLMAP (
employee_id = employee_id,
first_name = first_name,
last_name = last_name,
email = email,
hire_date = hire_date,
salary = salary * 1.1 — salary increase
);
“`
– **过滤条件:**
“`
MAP source.employees, TARGET target.employees,
FILTER (department_id = 10);
“`
– **函数转换:**
“`
MAP source.employees, TARGET target.employees,
COLMAP (
employee_id = employee_id,
full_name = CONCAT(first_name, ‘ ‘, last_name),
hire_year = EXTRACT(YEAR FROM hire_date)
);
“`
## 2. SQL数据转换
– **数据类型转换:**
“`sql
— 字符串转日期
SELECT TO_DATE(‘2024-01-01’, ‘YYYY-MM-DD’) FROM dual;
— 日期转字符串
SELECT TO_CHAR(SYSDATE, ‘YYYY-MM-DD HH24:MI:SS’) FROM dual;
— 数字转字符串
SELECT TO_CHAR(12345, ‘99999’) FROM dual;
— 字符串转数字
SELECT TO_NUMBER(‘12345’) FROM dual;
“`
– **条件转换:**
“`sql
SELECT employee_id, first_name, last_name,
CASE
WHEN salary < 5000 THEN 'Low'
WHEN salary >= 5000 AND salary < 10000 THEN 'Medium'
ELSE 'High'
END AS salary_level
FROM fgedu.employees;
```
- **聚合转换:**
```sql
SELECT department_id,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary
FROM fgedu.employees
GROUP BY department_id;
```
## 3. 数据处理
- **批量处理:**
```sql
-- 批量更新
UPDATE /*+ BATCHED_UPDATES */ fgedu.employees
SET salary = salary * 1.1
WHERE department_id = 10;
-- 批量插入
INSERT /*+ APPEND */ INTO fgedu.employees_backup
SELECT * FROM fgedu.employees;
```
- **并行处理:**
```sql
-- 并行查询
SELECT /*+ PARALLEL(4) */ * FROM fgedu.employees;
-- 并行更新
UPDATE /*+ PARALLEL(4) */ fgedu.employees
SET salary = salary * 1.1;
```
- **分区处理:**
```sql
-- 分区查询
SELECT * FROM fgedu.orders PARTITION (p202401);
-- 分区维护
ALTER TABLE fgedu.orders ADD PARTITION p202403 VALUES LESS THAN (TO_DATE('2024-04-01', 'YYYY-MM-DD'));
```
3.4 SQL性能优化
SQL性能优化是提高GoldenGate同步效率的重要因素:
## 1. 查询优化
– **使用索引:**
“`sql
— 创建索引
CREATE INDEX emp_dept_idx ON fgedu.employees(department_id);
— 使用索引的查询
SELECT * FROM fgedu.employees WHERE department_id = 10;
“`
– **避免全表扫描:**
“`sql
— 不好的查询(全表扫描)
SELECT * FROM fgedu.employees WHERE salary > 5000;
— 好的查询(使用索引)
CREATE INDEX emp_salary_idx ON fgedu.employees(salary);
SELECT * FROM fgedu.employees WHERE salary > 5000;
“`
– **使用绑定变量:**
“`sql
— 不好的查询(硬解析)
SELECT * FROM fgedu.employees WHERE employee_id = 1001;
— 好的查询(软解析)
SELECT * FROM fgedu.employees WHERE employee_id = :emp_id;
“`
## 2. DML优化
– **批量操作:**
“`sql
— 单行插入
INSERT INTO fgedu.employees VALUES (1001, ‘John’, ‘Doe’, …);
— 多行插入
INSERT INTO fgedu.employees VALUES
(1001, ‘John’, ‘Doe’, …),
(1002, ‘Jane’, ‘Smith’, …),
(1003, ‘Mike’, ‘Johnson’, …);
“`
– **使用FORALL:**
“`plsql
DECLARE
TYPE emp_tab IS TABLE OF fgedu.employees%ROWTYPE;
emp_records emp_tab;
BEGIN
— 填充数据
SELECT * BULK COLLECT INTO emp_records FROM fgedu.employees WHERE department_id = 10;
— 批量更新
FORALL i IN emp_records.FIRST..emp_records.LAST
UPDATE fgedu.employees SET salary = salary * 1.1 WHERE employee_id = emp_records(i).employee_id;
COMMIT;
END;
/
“`
– **使用MERGE语句:**
“`sql
MERGE INTO fgedu.employees e
USING (SELECT employee_id, first_name, last_name, salary FROM source_employees)
ON (e.employee_id = source_employees.employee_id)
WHEN MATCHED THEN
UPDATE SET e.first_name = source_employees.first_name,
e.last_name = source_employees.last_name,
e.salary = source_employees.salary
WHEN NOT MATCHED THEN
INSERT (employee_id, first_name, last_name, salary)
VALUES (source_employees.employee_id, source_employees.first_name, source_employees.last_name, source_employees.salary);
“`
## 3. 执行计划分析
– **查看执行计划:**
“`sql
EXPLAIN PLAN FOR
SELECT * FROM fgedu.employees WHERE department_id = 10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
“`
– **使用AUTOTRACE:**
“`sql
SET AUTOTRACE ON
SELECT * FROM fgedu.employees WHERE department_id = 10;
“`
– **识别性能瓶颈:**
“`sql
— 查看长时间运行的SQL
SELECT sql_id, sql_text, elapsed_time, cpu_time, disk_reads, buffer_gets
FROM v$sql
WHERE elapsed_time > 1000000
ORDER BY elapsed_time DESC;
“`
## 4. 数据库参数优化
– **调整PGA:**
“`sql
ALTER SYSTEM SET pga_aggregate_target = 1G SCOPE=SPFILE;
“`
– **调整SGA:**
“`sql
ALTER SYSTEM SET sga_target = 4G SCOPE=SPFILE;
“`
– **调整共享池:**
“`sql
ALTER SYSTEM SET shared_pool_size = 1G SCOPE=SPFILE;
“`
Part04-生产案例与实战讲解
4.1 SQL开发案例
以下是一个SQL开发的实战案例:
## 案例:员工管理系统SQL开发
### 背景
– 客户:某企业
– 系统:Oracle Database 19c,GoldenGate 19c
– 需求:开发员工管理系统的SQL脚本,包括表结构创建、数据操作、查询优化等
### 实施步骤
1. **表结构设计:**
“`sql
— 创建部门表
CREATE TABLE fgedu.departments (
department_id NUMBER(4) PRIMARY KEY,
department_name VARCHAR2(30) NOT NULL,
manager_id NUMBER(6),
location_id NUMBER(4)
);
— 创建员工表
CREATE TABLE fgedu.employees (
employee_id NUMBER(6) PRIMARY KEY,
first_name VARCHAR2(20),
last_name VARCHAR2(25) NOT NULL,
email VARCHAR2(25) NOT NULL,
phone_number VARCHAR2(20),
hire_date DATE NOT NULL,
job_id VARCHAR2(10) NOT NULL,
salary NUMBER(8,2),
commission_pct NUMBER(2,2),
manager_id NUMBER(6),
department_id NUMBER(4),
CONSTRAINT emp_email_uk UNIQUE (email),
CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES fgedu.departments(department_id)
);
— 创建索引
CREATE INDEX emp_dept_idx ON fgedu.employees(department_id);
CREATE INDEX emp_job_idx ON fgedu.employees(job_id);
CREATE INDEX emp_manager_idx ON fgedu.employees(manager_id);
“`
2. **数据插入:**
“`sql
— 插入部门数据
INSERT INTO fgedu.departments VALUES (10, ‘Administration’, 200, 1700);
INSERT INTO fgedu.departments VALUES (20, ‘Marketing’, 201, 1800);
INSERT INTO fgedu.departments VALUES (30, ‘Purchasing’, 114, 1700);
— 插入员工数据
INSERT INTO fgedu.employees VALUES (100, ‘Steven’, ‘King’, ‘steven.king@example.com’, ‘515.123.4567’, TO_DATE(‘2003-06-17’, ‘YYYY-MM-DD’), ‘AD_PRES’, 24000, NULL, NULL, 90);
INSERT INTO fgedu.employees VALUES (101, ‘Neena’, ‘Kochhar’, ‘neena.kochhar@example.com’, ‘515.123.4568’, TO_DATE(‘2005-09-21’, ‘YYYY-MM-DD’), ‘AD_VP’, 17000, NULL, 100, 90);
INSERT INTO fgedu.employees VALUES (102, ‘Lex’, ‘De Haan’, ‘lex.dehaan@example.com’, ‘515.123.4569’, TO_DATE(‘2001-01-13’, ‘YYYY-MM-DD’), ‘AD_VP’, 17000, NULL, 100, 90);
“`
3. **查询优化:**
“`sql
— 优化前的查询
SELECT e.employee_id, e.first_name, e.last_name, e.salary, d.department_name
FROM fgedu.employees e, fgedu.departments d
WHERE e.department_id = d.department_id AND e.salary > 10000;
— 优化后的查询
SELECT /*+ USE_NL(e d) */ e.employee_id, e.first_name, e.last_name, e.salary, d.department_name
FROM fgedu.employees e
JOIN fgedu.departments d ON e.department_id = d.department_id
WHERE e.salary > 10000;
— 创建索引
CREATE INDEX emp_salary_idx ON fgedu.employees(salary);
“`
4. **数据转换:**
“`sql
— 数据类型转换
SELECT employee_id, first_name, last_name,
TO_CHAR(hire_date, ‘YYYY-MM-DD’) AS hire_date_str,
TO_CHAR(salary, ‘99999.99’) AS salary_str
FROM fgedu.employees;
— 条件转换
SELECT employee_id, first_name, last_name, salary,
CASE
WHEN salary < 5000 THEN 'Low'
WHEN salary >= 5000 AND salary < 10000 THEN 'Medium'
ELSE 'High'
END AS salary_level
FROM fgedu.employees;
```
5. **性能监控:**
```sql
-- 查看执行计划
EXPLAIN PLAN FOR
SELECT * FROM fgedu.employees WHERE department_id = 10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- 查看SQL执行统计
SET AUTOTRACE ON
SELECT * FROM fgedu.employees WHERE department_id = 10;
```
### 实施结果
- 成功创建员工管理系统的表结构
- 实现了数据的插入、查询、更新和删除操作
- 优化了SQL查询性能,提高了系统响应速度
- 实现了数据转换和处理功能
- 建立了性能监控机制,确保系统的稳定运行
4.2 数据转换案例
以下是一个数据转换的实战案例:
## 案例:GoldenGate数据转换实现
### 背景
– 客户:某金融企业
– 系统:Oracle Database 19c,GoldenGate 19c
– 需求:在数据同步过程中进行数据转换,包括字段映射、数据过滤、业务逻辑转换等
### 实施步骤
1. **源端和目标端表结构:**
“`sql
— 源端表
CREATE TABLE source.customer (
customer_id NUMBER(10) PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50),
email VARCHAR2(100),
phone VARCHAR2(20),
address VARCHAR2(200),
status VARCHAR2(10),
create_date DATE
);
— 目标端表
CREATE TABLE target.customer (
customer_id NUMBER(10) PRIMARY KEY,
full_name VARCHAR2(100),
contact_info VARCHAR2(120),
address VARCHAR2(200),
status_code NUMBER(1),
create_date TIMESTAMP
);
“`
2. **GoldenGate配置:**
“`
— 配置Extract进程
EXTRACT ext1
USERID ggadmin, PASSWORD ggadmin123
EXTTRAIL /u01/app/goldengate/dirdat/et
TABLE source.customer;
— 配置Replicat进程
REPLICAT rep1
USERID ggadmin, PASSWORD ggadmin123
ASSUMETARGETDEFS
MAP source.customer, TARGET target.customer,
COLMAP (
customer_id = customer_id,
full_name = CONCAT(first_name, ‘ ‘, last_name),
contact_info = CONCAT(email, ‘ | ‘, phone),
address = address,
status_code = CASE status
WHEN ‘ACTIVE’ THEN 1
WHEN ‘INACTIVE’ THEN 0
ELSE -1
END,
create_date = CAST(create_date AS TIMESTAMP)
);
“`
3. **数据验证:**
“`sql
— 源端插入数据
INSERT INTO source.customer VALUES (1, ‘John’, ‘Doe’, ‘john.doe@example.com’, ‘123-456-7890’, ‘123 Main St’, ‘ACTIVE’, SYSDATE);
COMMIT;
— 目标端验证数据
SELECT * FROM target.customer;
“`
4. **性能优化:**
“`
— 优化Replicat进程
REPLICAT rep1
USERID ggadmin, PASSWORD ggadmin123
ASSUMETARGETDEFS
MAP source.customer, TARGET target.customer,
COLMAP (
customer_id = customer_id,
full_name = CONCAT(first_name, ‘ ‘, last_name),
contact_info = CONCAT(email, ‘ | ‘, phone),
address = address,
status_code = CASE status
WHEN ‘ACTIVE’ THEN 1
WHEN ‘INACTIVE’ THEN 0
ELSE -1
END,
create_date = CAST(create_date AS TIMESTAMP)
);
— 增加并行处理
PARALLEL 4;
“`
### 实施结果
– 成功实现了源端和目标端的数据同步
– 实现了字段映射、数据过滤、业务逻辑转换等功能
– 数据转换正确,满足业务需求
– 系统运行稳定,性能良好
Part05-风哥经验总结与分享
5.1 SQL开发经验总结
根据实际经验,总结以下SQL开发经验:
- 基础扎实:掌握SQL基础语法和核心概念,是进行高级SQL开发的前提。
- 性能优化:了解SQL执行计划,掌握索引设计和查询优化技巧,提高SQL执行效率。
- 数据建模:合理设计表结构和关系,确保数据完整性和查询效率。
- 代码规范:遵循SQL代码规范,提高代码的可读性和可维护性。
- 错误处理:添加适当的错误处理,提高代码的健壮性。
- 安全性:注意SQL注入等安全问题,使用参数化查询和权限控制。
- 持续学习:关注SQL的新特性和最佳实践,不断提升SQL技能。
- 实践经验:通过实际项目积累经验,提高解决问题的能力。
5.2 风哥SQL经验分享
在多年的SQL开发和GoldenGate实施经验中,我总结了以下几点心得:
1. 理解数据模型:深入理解业务数据模型,设计合理的表结构和关系,为SQL开发和GoldenGate同步奠定基础。
2. 掌握SQL优化技巧:了解SQL执行计划,掌握索引设计、查询优化、批量操作等技巧,提高SQL执行效率。
3. 合理使用GoldenGate转换功能:充分利用GoldenGate的数据转换功能,实现复杂的业务逻辑转换,减少目标端的处理压力。
4. 注意数据类型兼容性:确保源端和目标端的数据类型兼容,避免数据转换过程中的错误。
5. 监控和调优:建立SQL执行监控机制,及时发现和解决性能问题,确保系统的稳定运行。
6. 安全性考虑:注意SQL注入、权限控制等安全问题,确保数据安全。
7. 文档和注释:编写详细的SQL文档和注释,提高代码的可维护性。
8. 团队协作:与团队成员和业务人员密切协作,确保SQL开发和GoldenGate实施符合业务需求。
9. 持续学习:关注SQL和GoldenGate的新特性和最佳实践,不断提升技能水平。
10. 实践出真知:通过实际项目积累经验,提高解决问题的能力,成为SQL和GoldenGate专家。
更多学习教程公众号风哥教程itpux_com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
