最近用到批量插入数据到oracle,总结了网上的方案,内容如下
备注:亲测了三种方式的对比,参考网址:https://www.cnblogs.com/ggll611928/p/17897390.html
方式一:使用数组绑定
https://www.codenong.com/343299/
数据库:CREATE TABLE jkl_test (id NUMBER(9));
USING Oracle.DataAccess.Client; namespace OracleArrayInsertExample { class Program { static void Main(string[] args) { // OPEN a connection USING ODP.Net var connection = new OracleConnection("Data Source=YourDatabase; Password=YourPassword; User Id=YourUser"); connection.Open(); // CREATE an INSERT command var command = connection.CreateCommand(); command.CommandText ="insert into jkl_test values (:ids)"; // SET up the parameter AND provide VALUES var param = new OracleParameter("ids", OracleDbType.Int32); param.Value = new int[] { 22, 55, 7, 33, 11 }; // This IS critical TO the process; IN ORDER FOR the command TO // recognize AND bind arrays, an array bind COUNT must be specified. // SET it TO the LENGTH OF the array. command.ArrayBindCount = 5; command.Parameters.Add(param); command.ExecuteNonQuery(); } } }
方式二 使用绑定变量的方式二
https://blog.csdn.net/weixin_50478033/article/details/133983591
public int InsertBindParam(DataTable dt) { int recordCount = dt.Rows.Count, i = 0, count = 0; using (OracleCommand cmd = new OracleCommand()) { cmd.CommandText = "INSERT INTO TEST001(COL1,COL2,COL3) VALUES(:P_COL1,:P_COL2,:P_COL3)"; //指定单次需要处理的条数 cmd.ArrayBindCount = recordCount; int[] p_col1 = new int[recordCount]; string[] p_col2 = new string[recordCount]; DateTime[] p_col3 = new DateTime[recordCount]; cmd.Parameters.Add(new OracleParameter("P_COL1", OracleDbType.Int32, p_col1, ParameterDirection.Input)); cmd.Parameters.Add(new OracleParameter("P_COL2", OracleDbType.Varchar2, p_col2, ParameterDirection.Input)); cmd.Parameters.Add(new OracleParameter("P_COL3", OracleDbType.Date, p_col3, ParameterDirection.Input)); foreach (DataRow dr in dt.Rows) { p_col1[i] = Convert.ToInt32(dr["COL1"].ToString()); p_col2[i] = dr["COL2"].ToString(); p_col3[i] = DateTime.Now; } using (var con = new OracleConnection()) { con.ConnectionString = m_sConnection; con.Open(); cmd.Connection = con; //执行批处理操作,并返回影响行数 count = cmd.ExecuteNonQuery(); } return count; } }
方式三 使用OracleBulkCopy
https://www.cnblogs.com/longbky/p/8146965.html
public static bool ExcuteNonQuery(DataTable dt) { using (SqlConnection connection = new SqlConnection(connStr))//创建数据库连接 { using (SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connection)) { connection.Open(); //sqlbulkcopy.BulkCopyTimeout = 100; //超时之前操作完成所允许的秒数 sqlbulkcopy.BatchSize = dt.Rows.Count; //每一批次中的行数 sqlbulkcopy.DestinationTableName = dt.TableName; //服务器上目标表的名称 for (int i = 0; i < dt.Columns.Count; i++) { sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); //映射定义数据源中的列和目标表中的列之间的关系 } sqlbulkcopy.WriteToServer(dt); // 将DataTable数据上传到数据表中 } } return true; }
拷贝博主的内容
特别注意 sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
插入的时候列的顺序可以不一致,但名称和数据类型最好要保存一致。不一致时候,也能进行正确的转换,除了比如DataTime数据类型,不能插入一个无效的string时间字符串。
在插入数据的时候如果数据类型是Guid类型的时候。一定要创建列的时候一定要指定数据类型: dt.Columns.Add("UserID", typeof(System.Data.SqlTypes.SqlGuid));,
不然会报“来自数据源的 String 类型的给定值不能转换为指定目标列的类型 uniqueidentifier。”这个错。