C#实现Oracle数据库指定表全量数据控制台打印的问题
如何修改C# Oracle程序以适配任意表结构打印全量数据
嘿,我来帮你搞定这个问题!你的原代码只固定读取了第一列的数据,要实现适配所有表结构打印全量数据,咱们需要做几个关键修改——核心就是要动态遍历结果集的所有列,还要处理不同数据类型的字段,同时还得注意安全性问题。
原代码的问题点
原代码里reader.GetString(0)是硬编码取第一列的字符串值,这就导致只能看到第一列,而且如果第一列不是字符串类型还会报错。要适配任意表,得动态获取列的数量和每一列的值。
解决方案关键步骤
- 动态获取列数:利用
OracleDataReader.FieldCount属性拿到结果集的总列数,然后循环遍历每一列 - 处理不同数据类型:不要直接用
GetString,改用GetValue()方法,它能适配所有数据类型,再转成字符串输出;同时要处理DBNull的空值情况 - 打印表头(可选但友好):先打印每一列的列名,让输出结果更易读
- 防范SQL注入:原代码直接拼接用户输入的表名,这有很大的安全风险!咱们可以先查询Oracle的
USER_TABLES视图,验证用户输入的表名是否存在,避免恶意输入
修改后的完整代码
using System; using Oracle.ManagedDataAccess.Client; namespace Ass1Que1 { class Program { static void Main(string[] args) { try { string constr = "DATA SOURCE=localhost:1521/orclpdb;PERSIST SECURITY INFO=True;USER ID=HR;password=hr"; // 使用using自动释放资源,避免内存泄漏 using (OracleConnection con = new OracleConnection(constr)) { con.Open(); Console.WriteLine("Connected to Oracle Database {0}", con.ServerVersion); Console.Write("Enter the table name: "); string tableName = Console.ReadLine().Trim().ToUpper(); // 先验证表名合法性,彻底防范SQL注入 if (!IsTableExists(con, tableName)) { Console.WriteLine($"Error: Table '{tableName}' does not exist in HR schema!"); Console.WriteLine("Press RETURN to exit."); Console.ReadLine(); return; } // 执行查询 string sql = $"SELECT * FROM {tableName}"; using (OracleCommand cmd = con.CreateCommand()) { cmd.CommandText = sql; using (OracleDataReader reader = cmd.ExecuteReader()) { if (!reader.HasRows) { Console.WriteLine($"No data found in table '{tableName}'."); Console.WriteLine("Press RETURN to exit."); Console.ReadLine(); return; } // 打印表头:遍历所有列名 for (int i = 0; i < reader.FieldCount; i++) { Console.Write($"{reader.GetName(i),-20}"); // 格式化列名,左对齐占20字符 } Console.WriteLine("\n" + new string('-', reader.FieldCount * 20)); // 打印分隔线 // 遍历每一行数据 while (reader.Read()) { // 遍历当前行的所有列 for (int i = 0; i < reader.FieldCount; i++) { // 处理空值,将DBNull转为"NULL"字符串 string value = reader.IsDBNull(i) ? "NULL" : reader.GetValue(i).ToString(); Console.Write($"{value,-20}"); // 格式化输出,保持列对齐 } Console.WriteLine(); // 每行结束换行 } } } Console.WriteLine("\nPress RETURN to exit."); Console.ReadLine(); } } catch (Exception ex) { Console.WriteLine("Error : {0}", ex.Message); Console.ReadKey(); } } /// <summary> /// 验证HR用户下是否存在指定表 /// </summary> private static bool IsTableExists(OracleConnection connection, string tableName) { string checkSql = "SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = :tableName"; using (OracleCommand cmd = connection.CreateCommand()) { cmd.CommandText = checkSql; cmd.Parameters.Add(":tableName", OracleDbType.Varchar2).Value = tableName; int count = Convert.ToInt32(cmd.ExecuteScalar()); return count > 0; } } } }
关键修改说明
- 资源自动管理:用
using语句包裹连接、命令和读取器,自动释放资源,避免内存泄漏 - SQL注入防护:新增
IsTableExists方法,通过参数化查询验证表名合法性,彻底避免恶意输入风险 - 动态列处理:
- 用
reader.FieldCount获取总列数,循环打印列名作为表头 - 每行数据遍历所有列,用
GetValue(i)兼容所有数据类型,同时处理DBNull空值
- 用
- 格式化输出:用
{value,-20}让每列左对齐并固定宽度,输出结果更整齐易读
这样修改后,不管HR用户下的表结构是什么样的,程序都能自动识别所有列并打印全量数据,同时解决了原代码的安全隐患和数据类型兼容问题。
内容的提问来源于stack exchange,提问作者S_Madankar
相关产品推荐
相关产品推荐

