技术栈:
- .net core 3.1+ 或 .net 5/6/7/8 控制台应用
- 使用
system
,system.text.regularexpressions
,system.text
,system.text.json
,system.collections.generic
program.cs(完整代码)
using system; using system.collections.generic; using system.text; using system.text.regularexpressions; using system.text.json; namespace mysqltooracleconverter { // 数据结构扩展:新增包名配置、权限角色信息 public class procedureanalysisresult { public string procedurename { get; set; } = ""; public string packagename { get; set; } = "pkg_mysql_convert"; // 默认包名,可自定义 public list<string> grantroles { get; set; } = new list<string> { "app_user", "admin" }; // 默认授权角色 public list<parameterinfo> parameters { get; set; } = new list<parameterinfo>(); public string functiondescription { get; set; } = "请手动补充:根据代码逻辑归纳业务功能。"; public list<string> dmlstatements { get; set; } = new list<string>(); public list<selectinfo> selectqueries { get; set; } = new list<selectinfo>(); public list<variableinfo> variables { get; set; } = new list<variableinfo>(); public list<controlflowinfo> controlflows { get; set; } = new list<controlflowinfo>(); public list<cursorinfo> cursors { get; set; } = new list<cursorinfo>(); public list<string> exceptionhandlers { get; set; } = new list<string>(); public list<string> calledproceduresfunctions { get; set; } = new list<string>(); public list<string> uservariables { get; set; } = new list<string>(); public list<temptableinfo> temptables { get; set; } = new list<temptableinfo>(); public list<string> transactioncontrols { get; set; } = new list<string>(); public list<string> autoincrementtables { get; set; } = new list<string>(); public list<batchinsertinfo> batchinserts { get; set; } = new list<batchinsertinfo>(); } // 原有数据结构保持不变 public class batchinsertinfo { public string tablename { get; set; } = ""; public string columns { get; set; } = ""; public list<string> valuerows { get; set; } = new list<string>(); } public class sequenceinfo { public string sequencename { get; set; } = ""; public string tablename { get; set; } = ""; public string columnname { get; set; } = "id"; public int startwith { get; set; } = 1; public int incrementby { get; set; } = 1; } public class temptableinfo { public string tablename { get; set; } = ""; public string columndefinitions { get; set; } = ""; } public class parameterinfo { public string mode { get; set; } = ""; public string name { get; set; } = ""; public string datatype { get; set; } = ""; public int? typelength { get; set; } } public class selectinfo { public string sql { get; set; } = ""; public string usagehint { get; set; } = "可能是赋值或返回结果集"; } public class variableinfo { public string name { get; set; } = ""; public string datatype { get; set; } = ""; public int? typelength { get; set; } public string usagehint { get; set; } = ""; } public class controlflowinfo { public string type { get; set; } = ""; public string contentsnippet { get; set; } = ""; public string originalcode { get; set; } = ""; } public class cursorinfo { public string cursorname { get; set; } = ""; public string selectquery { get; set; } = ""; public string fetchinto { get; set; } = ""; public string looplabel { get; set; } = ""; } class program { static void main(string[] args) { console.writeline("=== mysql 存储过程转 oracle 工具(企业级终极版) ==="); console.writeline("请输入您的 mysql 存储过程代码(可多行,以 ===end=== 结束输入):"); string input = readmultilineinput("==="); var analysis = analyzemysqlstoredprocedure(input); // 允许用户自定义包名和授权角色 console.writeline($"\n当前默认包名:{analysis.packagename},默认授权角色:{string.join(",", analysis.grantroles)}"); console.writeline("是否使用默认配置?(输入n修改,其他键使用默认):"); string customconfig = console.readline()?.trim().toupper(); if (customconfig == "n") { console.writeline("请输入自定义包名(如pkg_user_manage):"); string custompkg = console.readline()?.trim(); if (!string.isnullorempty(custompkg)) analysis.packagename = custompkg; console.writeline("请输入授权角色(多个用逗号分隔,如app_user,admin):"); string customroles = console.readline()?.trim(); if (!string.isnullorempty(customroles)) analysis.grantroles = customroles.split(',').tolist(); } string json = jsonserializer.serialize(analysis, new jsonserializeroptions { writeindented = true }); console.writeline("\n=== 分析结果(结构化 json) ==="); console.writeline(json); console.writeline("\n=== 生成 oracle 企业级代码(含package+权限) ==="); string oraclecode = generateoracleenterprisecode(analysis); console.writeline(oraclecode); } static string readmultilineinput(string endmarker) { string input = ""; string line; while (!string.isnullorempty(line = console.readline())) { if (line.trim() == endmarker) break; input += line + "\n"; } return input; } static procedureanalysisresult analyzemysqlstoredprocedure(string sql) { var result = new procedureanalysisresult(); extractprocedurenameandparams(sql, result); extractdmlstatements(sql, result); extractselectqueries(sql, result); extractvariables(sql, result); extractcontrolflows(sql, result); extractcursors(sql, result); extractexceptionhandlers(sql, result); extractcalledproceduresandfunctions(sql, result); extractuservariables(sql, result); extracttemptables(sql, result); extracttransactioncontrols(sql, result); extractautoincrementtables(sql, result); extractbatchinserts(sql, result); return result; } #region 原有提取方法(保持兼容,无修改) static void extractprocedurenameandparams(string sql, procedureanalysisresult r) { var procmatch = regex.match(sql, @"create\s+procedure\s+(?:if not exists\s+)?([^\s(]+)\s*\((.*?)\)", regexoptions.ignorecase); if (procmatch.success) { r.procedurename = procmatch.groups[1].value.trim(); string paramssection = procmatch.groups[2].value.trim(); if (!string.isnullorempty(paramssection)) { var parammatches = regex.matches(paramssection, @"(in|out|inout)\s+([^\s,]+)\s+([^\s,(]+)(?:\((\d+)\))?", regexoptions.ignorecase); foreach (match m in parammatches) { if (m.groups.count >= 4) { r.parameters.add(new parameterinfo { mode = m.groups[1].value.trim().toupper(), name = m.groups[2].value.trim(), datatype = m.groups[3].value.trim().toupper(), typelength = m.groups[4].success ? int.parse(m.groups[4].value) : (int?)null }); } } } } } static void extractautoincrementtables(string sql, procedureanalysisresult r) { var createtablematches = regex.matches(sql, @"create\s+(temporary\s+)?table\s+([^\s(]+)\s*\([^)]*auto_increment[^)]*\)", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in createtablematches) { string tablename = m.groups[2].value.trim(); if (!r.autoincrementtables.contains(tablename) && !string.isnullorempty(tablename)) r.autoincrementtables.add(tablename); } var insertmatches = regex.matches(sql, @"insert\s+into\s+([^\s(]+)\s*\([^)]*\)\s+values", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in insertmatches) { string tablename = m.groups[1].value.trim(); string columns = regex.match(m.value, @"\(([^)]*)\)", regexoptions.singleline).groups[1].value; if (!columns.contains("id", stringcomparison.ordinalignorecase) && !r.autoincrementtables.contains(tablename)) r.autoincrementtables.add(tablename); } } static void extractbatchinserts(string sql, procedureanalysisresult r) { var batchmatches = regex.matches(sql, @"insert\s+into\s+([^\s(]+)\s*\(([^)]*)\)\s+values\s*\(([^;]*)\);", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in batchmatches) { if (m.groups.count < 4) continue; string tablename = m.groups[1].value.trim(); string columns = m.groups[2].value.trim(); string valuesblock = m.groups[3].value.trim(); var valuerows = regex.split(valuesblock, @"\)\s*,\s*\("); list<string> cleanrows = new list<string>(); foreach (var row in valuerows) { string cleanrow = row.trim().trim('(').trim(')'); if (!string.isnullorempty(cleanrow)) cleanrows.add($"({cleanrow})"); } if (cleanrows.count > 1) { r.batchinserts.add(new batchinsertinfo { tablename = tablename, columns = columns, valuerows = cleanrows }); } } } static void extractvariables(string sql, procedureanalysisresult r) { var varmatches = regex.matches(sql, @"declare\s+([^\s]+)\s+([^\s,(]+)(?:\((\d+)\))?(?:\s+default\s+[^;]+)?", regexoptions.ignorecase); foreach (match m in varmatches) { if (m.groups.count >= 3) { r.variables.add(new variableinfo { name = m.groups[1].value.trim(), datatype = m.groups[2].value.trim().toupper(), typelength = m.groups[3].success ? int.parse(m.groups[3].value) : (int?)null }); } } } static void extractcontrolflows(string sql, procedureanalysisresult r) { var ifmatches = regex.matches(sql, @"\bif\b.*?\bend if\b;", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in ifmatches) r.controlflows.add(new controlflowinfo { type = "if", originalcode = m.value.trim() }); var whilematches = regex.matches(sql, @"\bwhile\b.*?\bend while\b;", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in whilematches) r.controlflows.add(new controlflowinfo { type = "while", originalcode = m.value.trim() }); var loopmatches = regex.matches(sql, @"\bloop\b.*?\bend loop\b;", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in loopmatches) r.controlflows.add(new controlflowinfo { type = "loop", originalcode = m.value.trim() }); var casematches = regex.matches(sql, @"\bcase\b.*?\bend case\b;", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in casematches) r.controlflows.add(new controlflowinfo { type = "case", originalcode = m.value.trim() }); } static void extractcursors(string sql, procedureanalysisresult r) { var cursordeclares = regex.matches(sql, @"declare\s+([^\s]+)\s+cursor\s+for\s+(.+?);", regexoptions.ignorecase | regexoptions.singleline); foreach (match declarematch in cursordeclares) { string cursorname = declarematch.groups[1].value.trim(); string selectquery = declarematch.groups[2].value.trim(); string fetchpattern = $@"fetch\s+{cursorname}\s+into\s+([^;]+);"; var fetchmatch = regex.match(sql, fetchpattern, regexoptions.ignorecase | regexoptions.singleline); string looplabelpattern = $@"(\w+):\s+loop\s+.*?fetch\s+{cursorname}"; var looplabelmatch = regex.match(sql, looplabelpattern, regexoptions.ignorecase | regexoptions.singleline); r.cursors.add(new cursorinfo { cursorname = cursorname, selectquery = selectquery, fetchinto = fetchmatch.success ? fetchmatch.groups[1].value.trim() : "", looplabel = looplabelmatch.success ? looplabelmatch.groups[1].value.trim() : $"{cursorname}_loop" }); } } static void extracttemptables(string sql, procedureanalysisresult r) { var tempmatches = regex.matches(sql, @"create\s+temporary\s+table\s+([^\s(]+)\s*\((.*?)\);", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in tempmatches) { if (m.groups.count >= 3) { r.temptables.add(new temptableinfo { tablename = m.groups[1].value.trim(), columndefinitions = m.groups[2].value.trim() }); } } } static void extractdmlstatements(string sql, procedureanalysisresult r) { var dmlkeywords = new[] { "insert", "update", "delete" }; foreach (var keyword in dmlkeywords) { var matches = regex.matches(sql, $@"\b{keyword}\b[^;]*;", regexoptions.ignorecase); foreach (match m in matches) r.dmlstatements.add(m.value.trim()); } } static void extractselectqueries(string sql, procedureanalysisresult r) { var selectmatches = regex.matches(sql, @"\bselect\b[^;]*;", regexoptions.ignorecase); foreach (match m in selectmatches) { r.selectqueries.add(new selectinfo { sql = m.value.trim(), usagehint = m.value.indexof("into", stringcomparison.ordinalignorecase) >= 0 ? "赋值语句(into)" : "结果集查询" }); } } static void extractexceptionhandlers(string sql, procedureanalysisresult r) { var handlermatches = regex.matches(sql, @"declare\s+handler\s+for\s+(.+?)\s+(.+?);", regexoptions.ignorecase | regexoptions.singleline); foreach (match m in handlermatches) r.exceptionhandlers.add(m.value.trim()); } static void extractcalledproceduresandfunctions(string sql, procedureanalysisresult r) { var callmatches = regex.matches(sql, @"\bcall\s+([^\s(]+)|\b([^\s(]+)\s*\(", regexoptions.ignorecase); foreach (match m in callmatches) { foreach (group g in m.groups) { if (g.success && !string.isnullorempty(g.value) && !g.value.equals("call", stringcomparison.ordinalignorecase) && !r.calledproceduresfunctions.contains(g.value)) r.calledproceduresfunctions.add(g.value.trim()); } } } static void extractuservariables(string sql, procedureanalysisresult r) { var uservarmatches = regex.matches(sql, @"@\w+", regexoptions.ignorecase); foreach (match m in uservarmatches) if (!r.uservariables.contains(m.value)) r.uservariables.add(m.value); } static void extracttransactioncontrols(string sql, procedureanalysisresult r) { var transmatches = regex.matches(sql, @"\b(commit|rollback)\b", regexoptions.ignorecase); foreach (match m in transmatches) r.transactioncontrols.add(m.value.trim().toupper()); } #endregion #region 核心优化:生成企业级oracle代码(package+权限) static string generateoracleenterprisecode(procedureanalysisresult analysis) { var sb = new stringbuilder(); // 1. 生成sequence(自增适配) if (analysis.autoincrementtables.count > 0) { sb.appendline("-- === 1. sequence定义(适配mysql自增id)==="); foreach (var tablename in analysis.autoincrementtables) { sequenceinfo seq = createsequencefortable(tablename); sb.appendline($"create sequence {seq.sequencename}"); sb.appendline($" start with {seq.startwith}"); sb.appendline($" increment by {seq.incrementby}"); sb.appendline($" nocache nocycle;"); sb.appendline($"create or replace trigger trg_{tablename}_{seq.columnname}"); sb.appendline($" before insert on {tablename}"); sb.appendline($" for each row"); sb.appendline($"begin"); sb.appendline($" if :new.{seq.columnname} is null then"); sb.appendline($" select {seq.sequencename}.nextval into :new.{seq.columnname} from dual;"); sb.appendline($" end if;"); sb.appendline($"end;"); sb.appendline("/\n"); } } // 2. 生成临时表 if (analysis.temptables.count > 0) { sb.appendline("-- === 2. 临时表定义(oracle全局临时表)==="); foreach (var temptable in analysis.temptables) { string oraclecols = convertmysqltemptablecolstooracle(temptable.columndefinitions); sb.appendline($"create global temporary table {temptable.tablename} ("); sb.appendline($" {oraclecols}"); sb.appendline(") on commit delete rows;"); sb.appendline(); } } // 3. 生成package规范(package spec):声明存储过程接口 sb.appendline($"-- === 3. 包规范({analysis.packagename} spec)==="); sb.appendline($"create or replace package {analysis.packagename} as"); sb.appendline(); sb.appendline($" -- 存储过程接口声明(参数与原mysql一致)"); sb.appendline($" procedure {analysis.procedurename}("); for (int i = 0; i < analysis.parameters.count; i++) { var p = analysis.parameters[i]; string oracletype = mapmysqltypetooracle(p.datatype, p.typelength); string mode = p.mode switch { "in" => "in ", "out" => "out ", "inout" => "in out ", _ => "in " }; string paramline = $" {mode}{p.name} {oracletype}"; if (i < analysis.parameters.count - 1) paramline += ","; sb.appendline(paramline); } sb.appendline($" );"); sb.appendline(); sb.appendline($" -- 可在此添加更多存储过程/函数接口(模块化扩展)"); sb.appendline($"end {analysis.packagename};"); sb.appendline("/\n"); // 4. 生成package体(package body):实现存储过程逻辑 sb.appendline($"-- === 4. 包体({analysis.packagename} body)==="); sb.appendline($"create or replace package body {analysis.packagename} as"); sb.appendline(); sb.appendline($" -- 存储过程实现"); sb.appendline($" procedure {analysis.procedurename}("); for (int i = 0; i < analysis.parameters.count; i++) { var p = analysis.parameters[i]; string oracletype = mapmysqltypetooracle(p.datatype, p.typelength); string mode = p.mode switch { "in" => "in ", "out" => "out ", "inout" => "in out ", _ => "in " }; string paramline = $" {mode}{p.name} {oracletype}"; if (i < analysis.parameters.count - 1) paramline += ","; sb.appendline(paramline); } sb.appendline($" )"); sb.appendline($" is"); // 4.1 变量声明(包体内局部变量) foreach (var v in analysis.variables) { string oracletype = mapmysqltypetooracle(v.datatype, v.typelength); sb.appendline($" {v.name} {oracletype}; -- mysql原类型: {v.datatype}{(v.typelength.hasvalue ? $"({v.typelength})" : "")}"); } // 4.2 游标声明(包体内局部游标) if (analysis.cursors.count > 0) { sb.appendline(); sb.appendline($" -- 游标定义(包体内局部游标)"); foreach (var cursor in analysis.cursors) { string oracleselect = convertmysqlselecttooracle(cursor.selectquery); sb.appendline($" cursor {cursor.cursorname} is {oracleselect};"); sb.appendline($" {cursor.cursorname}_notfound boolean := false;"); } } sb.appendline(); sb.appendline($" begin"); // 4.3 批量insert处理(包体内逻辑) if (analysis.batchinserts.count > 0) { sb.appendline(); sb.appendline($" -- 批量插入(oracle insert all 语法)"); foreach (var batch in analysis.batchinserts) { string finalcolumns = batch.columns; list<string> finalvalues = new list<string>(); if (analysis.autoincrementtables.contains(batch.tablename)) { string seqname = $"seq_{batch.tablename}_id"; if (!batch.columns.contains("id", stringcomparison.ordinalignorecase)) finalcolumns = $"id, {batch.columns}"; foreach (var row in batch.valuerows) { string rowwithseq = row.replace("(", $"({seqname}.nextval, "); finalvalues.add(rowwithseq); } } else { finalvalues = batch.valuerows; } sb.appendline($" insert all"); foreach (var val in finalvalues) { sb.appendline($" into {batch.tablename} ({finalcolumns}) values {val}"); } sb.appendline($" select 1 from dual;"); } } // 4.4 游标循环处理 if (analysis.cursors.count > 0) { sb.appendline(); sb.appendline($" -- 游标循环处理"); foreach (var cursor in analysis.cursors) { if (string.isnullorempty(cursor.fetchinto)) continue; sb.appendline($" open {cursor.cursorname};"); sb.appendline($" {cursor.looplabel}: loop"); sb.appendline($" fetch {cursor.cursorname} into {cursor.fetchinto};"); sb.appendline($" if {cursor.cursorname}%notfound then"); sb.appendline($" set {cursor.cursorname}_notfound := true;"); sb.appendline($" exit {cursor.looplabel};"); sb.appendline($" end if;"); sb.appendline($" -- 游标数据处理(原mysql逻辑)"); sb.appendline($" end loop {cursor.looplabel};"); sb.appendline($" close {cursor.cursorname};"); } } // 4.5 普通dml/select处理 sb.appendline(); sb.appendline($" -- 普通业务逻辑"); foreach (var sel in analysis.selectqueries) { string oracleselect = convertmysqlselecttooracle(sel.sql); sb.appendline($" {oracleselect}"); } foreach (var dml in analysis.dmlstatements) { if (!isbatchinsert(dml, analysis.batchinserts)) { string oracledml = convertmysqldmltooracle(dml, analysis.autoincrementtables); sb.appendline($" {oracledml}"); } } // 4.6 事务控制 foreach (var trans in analysis.transactioncontrols) { sb.appendline($" {trans};"); } // 4.7 异常处理 if (analysis.exceptionhandlers.count > 0 || analysis.cursors.count > 0) { sb.appendline(); sb.appendline($" -- 异常处理(含游标清理)"); sb.appendline($" exception"); sb.appendline($" when others then"); foreach (var cursor in analysis.cursors) { sb.appendline($" if {cursor.cursorname}%isopen then"); sb.appendline($" close {cursor.cursorname};"); sb.appendline($" end if;"); } foreach (var handler in analysis.exceptionhandlers) { string oracleexception = convertmysqlhandlertooracle(handler); sb.appendline($" {oracleexception}"); } sb.appendline($" dbms_output.put_line('{analysis.procedurename} 异常:' || sqlerrm || '(行号:' || sqlcode || ')');"); } sb.appendline($" end {analysis.procedurename};"); sb.appendline(); sb.appendline($" -- 可在此添加更多存储过程/函数实现(模块化扩展)"); sb.appendline($"end {analysis.packagename};"); sb.appendline("/\n"); // 5. 生成权限分配语句(grant) sb.appendline($"-- === 5. 权限分配语句(控制访问权限)==="); foreach (var role in analysis.grantroles) { string cleanrole = role.trim(); if (string.isnullorempty(cleanrole)) continue; // 授权包的执行权限 sb.appendline($"grant execute on {analysis.packagename} to {cleanrole};"); // 若有临时表,授权临时表的操作权限 foreach (var temptable in analysis.temptables) { sb.appendline($"grant insert, update, delete, select on {temptable.tablename} to {cleanrole};"); } // 若有自增表,授权表的操作权限 foreach (var autotable in analysis.autoincrementtables) { sb.appendline($"grant insert, update, delete, select on {autotable} to {cleanrole};"); } sb.appendline(); } // 6. 生成调用示例 sb.appendline($"-- === 6. 存储过程调用示例(包内调用)==="); sb.appendline($"-- 调用格式:{analysis.packagename}.{analysis.procedurename}(参数列表)"); string callparams = string.join(", ", analysis.parameters.select(p => { if (p.mode == "out") return "null /* out参数需用变量接收 */"; return p.datatype switch { "int" or "integer" => "0", "varchar" or "varchar2" => "'测试值'", "date" or "datetime" => "sysdate", _ => "null" }; })); sb.appendline($"begin"); sb.appendline($" {analysis.packagename}.{analysis.procedurename}({callparams});"); sb.appendline($" commit;"); sb.appendline($"exception"); sb.appendline($" when others then"); sb.appendline($" rollback;"); sb.appendline($" dbms_output.put_line('调用异常:' || sqlerrm);"); sb.appendline($"end;"); sb.appendline("/"); return sb.tostring(); } #region 辅助方法(保持兼容,新增权限相关逻辑) static sequenceinfo createsequencefortable(string tablename) { return new sequenceinfo { sequencename = $"seq_{tablename}_id", tablename = tablename, columnname = "id", startwith = 1, incrementby = 1 }; } static bool isbatchinsert(string dml, list<batchinsertinfo> batches) { foreach (var batch in batches) { if (dml.contains($"insert into {batch.tablename}", stringcomparison.ordinalignorecase) && dml.contains("values", stringcomparison.ordinalignorecase)) { return true; } } return false; } static string convertmysqldmltooracle(string mysqldml, list<string> autotables) { string oracledml = mysqldml; foreach (var table in autotables) { if (oracledml.contains($"insert into {table}", stringcomparison.ordinalignorecase) && !oracledml.contains("id", stringcomparison.ordinalignorecase)) { string seqname = $"seq_{table}_id"; oracledml = regex.replace(oracledml, @"(insert into \w+)\s*\(([^)]*)\)", $"$1 (id, $2)", regexoptions.ignorecase); oracledml = regex.replace(oracledml, @"values\s*\(([^)]*)\)", $"values ({seqname}.nextval, $1)", regexoptions.ignorecase); } } oracledml = regex.replace(oracledml, @"now\(\)", "sysdate", regexoptions.ignorecase); oracledml = regex.replace(oracledml, @"auto_increment", "/* 已通过sequence实现自增 */", regexoptions.ignorecase); return oracledml; } static string convertmysqltemptablecolstooracle(string mysqlcols) { string[] colarray = mysqlcols.split(new[] { "," }, stringsplitoptions.removeemptyentries); list<string> oraclecols = new list<string>(); foreach (string col in colarray) { var colmatch = regex.match(col.trim(), @"([^\s]+)\s+([^\s(]+)(?:\((\d+)\))?", regexoptions.ignorecase); if (colmatch.success) { string colname = colmatch.groups[1].value.trim(); string mysqltype = colmatch.groups[2].value.trim().toupper(); int? length = colmatch.groups[3].success ? int.parse(colmatch.groups[3].value) : (int?)null; string oracletype = mapmysqltypetooracle(mysqltype, length); oraclecols.add($" {colname} {oracletype}"); } } return string.join(",\n", oraclecols); } static string convertmysqlselecttooracle(string mysqlselect) { string oracleselect = mysqlselect; var limitmatch = regex.match(oracleselect, @"limit\s+(\d+),\s*(\d+)", regexoptions.ignorecase); if (limitmatch.success) { int offset = int.parse(limitmatch.groups[1].value); int count = int.parse(limitmatch.groups[2].value); oracleselect = regex.replace(oracleselect, @"limit\s+\d+,\s*\d+", "", regexoptions.ignorecase); oracleselect = $"select * from (select t.*, rownum rn from ({oracleselect}) t where rownum <= {offset + count}) where rn > {offset}"; } else { oracleselect = regex.replace(oracleselect, @"limit\s+(\d+)", "where rownum <= $1", regexoptions.ignorecase); } oracleselect = regex.replace(oracleselect, @"now\(\)", "sysdate", regexoptions.ignorecase); oracleselect = regex.replace(oracleselect, @"curdate\(\)", "trunc(sysdate)", regexoptions.ignorecase); return oracleselect; } static string mapmysqltypetooracle(string mysqltype, int? length) { return mysqltype switch { "int" or "integer" => "number(10)", "smallint" => "number(5)", "tinyint" => "number(3)", "bigint" => "number(19)", "varchar" or "varchar2" or "char" => length.hasvalue ? $"varchar2({length})" : "varchar2(4000)", "text" => "varchar2(4000)", "longtext" => "clob", "datetime" => "timestamp", "timestamp" => "timestamp", "date" => "date", "boolean" or "bool" => "number(1)", "decimal" or "numeric" => length.hasvalue ? $"number({length})" : "number", "float" => "binary_float", "double" => "binary_double", "blob" => "blob", "clob" => "clob", _ => length.hasvalue ? $"varchar2({length})" : "varchar2(4000)" }; } static string convertmysqlhandlertooracle(string mysqlhandler) { if (regex.ismatch(mysqlhandler, @"exit\s+handler\s+for\s+sqlexception", regexoptions.ignorecase)) { string action = regex.match(mysqlhandler, @"for\s+sqlexception\s+(.+?);", regexoptions.ignorecase | regexoptions.singleline).groups[1].value; return $"{action};"; } if (regex.ismatch(mysqlhandler, @"continue\s+handler\s+for\s+not found", regexoptions.ignorecase)) { string action = regex.match(mysqlhandler, @"for\s+not found\s+(.+?);", regexoptions.ignorecase | regexoptions.singleline).groups[1].value; return $"{action};"; } return "dbms_output.put_line('未知异常');"; } #endregion #endregion } }
mysql自增id适配:自动生成oracle sequence与触发器
核心逻辑
- 自增表识别:通过两种场景判断含自增id的表:
1. create table 中含 auto_increment 关键字(如 id int auto_increment );
2. insert 语句字段不含 id (默认 id 为自增字段,如 insert into users(name) values(‘a’) )。 - sequence生成:按 seq_表名_id 规范生成序列(如 seq_users_id ),默认起始值1、步长1,配置 nocache nocycle 避免缓存浪费。
- 触发器自动关联:生成 trg_表名_id 触发器,在 insert 时自动为 id 字段赋值 sequence.nextval ,完全模拟mysql自增行为。
示例转换
mysql自增表创建:
create table users ( id int auto_increment primary key, name varchar(50) );
生成oracle代码:
-- sequence定义(适配mysql自增id) create sequence seq_users_id start with 1 increment by 1 nocache nocycle; create or replace trigger trg_users_id before insert on users for each row begin if :new.id is null then select seq_users_id.nextval into :new.id from dual; end if; end; /
mysql批量insert优化:转换为oracle insert all语法
核心逻辑
- 批量insert识别:提取mysql中 insert into … values(…),(…) 格式的批量语句(如 values((1,‘a’),(2,‘b’)) )。
- 语法转换规则:
1. 拆分行值:将 (1,‘a’),(2,‘b’) 拆分为 (1,‘a’) 和 (2,‘b’) ;
2. 自增表适配:若表含自增id,自动在字段列表添加 id ,值列表添加 sequence.nextval ;
3. 生成 insert all :通过 insert all into 表名(字段) values(值) select 1 from dual 实现批量插入(oracle批量插入必须以 select 1 from dual 结尾)。
示例转换
mysql批量insert:
insert into users(name) values('张三'),('李四'),('王五');
生成oracle代码:
-- 批量插入(转换为oracle insert all) insert all into users (id, name) values (seq_users_id.nextval, '张三') into users (id, name) values (seq_users_id.nextval, '李四') into users (id, name) values (seq_users_id.nextval, '王五') select 1 from dual; -- 必须添加select 1 from dual
完整运行效果示例(含自增+批量insert)
输入mysql存储过程:
create procedure batch_add_users(in dept_id int) begin -- 批量插入3个用户 insert into users(name, dept_id) values ('张三', dept_id), ('李四', dept_id), ('王五', dept_id); -- 插入自增表(省略id) insert into logs(content) values('批量添加用户'); commit; end;
生成oracle代码(关键部分):
-- 1. sequence定义(适配mysql自增id) create sequence seq_users_id start with 1 increment by 1 nocache nocycle; create or replace trigger trg_users_id before insert on users for each row begin if :new.id is null then select seq_users_id.nextval into :new.id from dual; end if; end; / create sequence seq_logs_id start with 1 increment by 1 nocache nocycle; create or replace trigger trg_logs_id before insert on logs for each row begin if :new.id is null then select seq_logs_id.nextval into :new.id from dual; end if; end; / -- 3. 存储过程 batch_add_users create or replace procedure batch_add_users( in dept_id number(10) ) is begin -- 批量插入(转换为oracle insert all) insert all into users (id, name, dept_id) values (seq_users_id.nextval, '张三', dept_id) into users (id, name, dept_id) values (seq_users_id.nextval, '李四', dept_id) into users (id, name, dept_id) values (seq_users_id.nextval, '王五', dept_id) select 1 from dual; -- 必须添加select 1 from dual -- 普通业务逻辑 insert into logs (id, content) values (seq_logs_id.nextval, '批量添加用户'); commit; -- 异常处理(含游标清理) exception when others then dbms_output.put_line('异常:' || sqlerrm || '(行号:' || sqlcode || ')'); end; / ```
以上就是c#程序实现将mysql的存储过程转换成oracle的存储过程的详细内容,更多关于c# mysql存储转换成oracle存储的资料请关注代码网其它相关文章!
发表评论