【问题标题】:How to Insert Data from DataTable to Oracle Database Table :如何将数据从 DataTable 插入 Oracle 数据库表:
【发布时间】:2021-07-12 22:23:57
【问题描述】:

我在 DataTable 中有 2 行 3 列的数据。我想将该数据插入到Oracle 表中。

如何插入?请举个例子。

还有

如何将数据表传递给 ORACLE 中的存储过程...

我以下面提到的方式传递数据表,但数据表类型问题即将到来。我该如何解决?

cmd.Parameters.Add("@Details",dtSupplier);   
(OR)  
cmd.Parameters.Add("Details", DbType.Single).Value = dtSupplier.ToString();

【问题讨论】:

  • 你能提供你看到的“类型问题”吗?它将帮助想要帮助您解决问题的人。

标签: c# asp.net


【解决方案1】:

想将数据集或数据表插入ORACLE,

  1. 创建一个 ORACLE 数据适配器。
  2. 为插入创建一个命令对象,
  3. 将 CommandType 设置为 StoredProcedure。
  4. 数据适配器的更新命令,
  5. 将数据集或数据表作为参数传递。

像这样:

OracleDataAdapter da = new OracleDataAdapter();
OracleCommand cmdOra = new OracleCommand(StoredProcedureName, Connection);
cmdOra.CommandType = CommandType.StoredProcedure;

da.InsertCommand = cmdOra;
da.Update(dsDataSet);

如果上述方法不起作用,则将数据表作为 xml 参数传递而不是处理它

详情查看:ADO.NET DataTable as XML parameter to an Oracle/SQL Server Database Stored Procedure

在 Oracle 网站上查看此线程:Thread: Pass data table to Oracle stored procedure

检查现有答案:How to Pass datatable as input to procedure in C#?

【讨论】:

【解决方案2】:

这个答案我非常迟到了,但我详细阐述了一些更易读(我希望)的代码,并避免所有这些.ToString()对于这些值,可以处理 nulls 和其他不太常见的值;在这里:

public void Copy(String tableName, DataTable dataTable)
{
    var insert = $"insert into {tableName} ({GetColumnNames(dataTable)}) values ({GetParamPlaceholders(dataTable)})";
    using (var connection = /*a method to get a new open connection*/)
    {       
        for (var row = 0; row < dataTable.Rows.Count; row++)
        {
            InsertRow(dataTable, insert, connection, row);
        }
    }
}

private static void InsertRow(DataTable dataTable, String insert, OracleConnection connection, Int32 row)
{
    using (var command = new OracleCommand(insert, connection))
    {
        AssembleParameters(dataTable, command, row);
        command.ExecuteNonQuery();
    }
}

private static void AssembleParameters(DataTable dataTable, OracleCommand command, Int32 row)
{
    for (var col = 0; col < dataTable.Columns.Count; col++)
    {
        command.Parameters.Add(ParameterFor(dataTable, row, col));
    }
}

private static OracleParameter ParameterFor(DataTable dataTable, Int32 row, Int32 col)
{
    return new OracleParameter(GetParamName(dataTable.Columns[col]), dataTable.Rows[row].ItemArray.GetValue(col));
}

private static String GetColumnNames(DataTable data) => (from DataColumn column in data.Columns select column.ColumnName).StringJoin(", ");

private static String GetParamPlaceholders(DataTable data) => (from DataColumn column in data.Columns select GetParamName(column)).StringJoin(", ");

private static String GetParamName(DataColumn column) => $":{column.ColumnName}_param";

希望这对某人仍然有用

【讨论】:

    【解决方案3】:

    最好的办法是按照下面提到的步骤进行

    1. 创建交易
    2. 开始交易
    3. 循环遍历数据表
    4. 调用您的程序
    5. 如果没有发生错误提交事务
    6. 否则回滚事务

    【讨论】:

      【解决方案4】:

      关于你的这部分问题:

      cmd.Parameters.Add("@Details",dtSupplier);
      (或)
      cmd.Parameters.Add("详细信息", DbType.Single).Value = dtSupplier.ToString();

      “详细信息”参数的类型是什么?是单曲吗?然后,您必须从 DataTable 中选择一 (1) 个值并将其传递给您的参数,例如 dtSupplier.Rows[0]["col"]。
      如果您使用 dtSupplier.ToString() 您只是在制作整个 DataTable 的字符串(我猜这将始终是 DataTable 的类型名称)。

      【讨论】:

        【解决方案5】:

        首先,您需要在 Visual Studio 中添加 Oracle.DataAccess.dll 作为引用。大多数情况下,你可以在C:\ProgramData\Oracle11g\product\11.2.0\client_1\ODP.NET\bin\2.x\Oracle.DataAccess.dll目录下找到这个dll

        如果您只是需要将数据表中的记录插入到 Oracle 表中,那么您可以调用以下函数。假设您的 DataTable 名称是 dt

        string error = "";
        int noOfInserts = DataTableToTable(dt,out error);
        

        1.不使用 Oracle 参数(特殊字符不安全)

        函数的定义如下。在这里,我们只是使查询动态化,以便将其作为 sql 语句传递给 InsertWithQuery 函数。

        public int DataTableToTable(DataTable dt,out string error)
        {
            error = "";
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                finalSql = "INSERT INTO TABLENAME SELECT ";
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    colValue += "'" + dt.Rows[i][j].ToString() + "',"; 
                }
                colValue = colValue.Remove(colValue.Length - 1, 1);
                finalSql += colValue + " FROM DUAL";
                InsertWithQuery(finalSql, out error);
                if (error != "")
                   return error;
                inserts++;
                colValue = "";
            }
        }
        

        InsertWithQuery 函数的代码如下。在这里,您必须在连接字符串中放置数据库详细信息,例如主机、用户名、密码等。

        public int InsertWithQuery(string query, out string error)
        {
             error = "";
             int rowsInserted = 0;        
             if (error == "")
             {
                  OracleConnection con = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=)(PORT=)))(CONNECT_DATA=(SERVER=DEDICATED)(SID=)));User Id=;Password="); 
                  OracleTransaction trans = con.BeginTransaction();              
                  try
                  {
                      error = "";
                      OracleCommand cmd = new OracleCommand();
                      cmd.Transaction = trans;
                      cmd.Connection = con;
                      cmd.CommandText = query;
                      rowsInserted = cmd.ExecuteNonQuery();
                      trans.Commit();
                      con.Dispose();
                      return rowsInserted;
                  }
                  catch (Exception ex)
                  {
                      trans.Rollback();
                      error = ex.Message;
                      rowsInserted = 0;
                  }
                  finally
                  {
                      con.Dispose();
                  }
             }
             return rowsInserted;
        }
        

        2。使用 Oracle 参数(特殊字符安全)
        这可以处理列值中的单引号等特殊字符。

        public int DataTableToTable(DataTable dt,out string error)
        {
            error = "";
            string finalSql = "";
            List<string> colValue = new List<string>();
            List<string> cols = new List<string>() {"COLUMN1","COLUMN2","COLUMN3"};
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                 finalSql = "INSERT INTO TABLENAME(COLUMN1,COLUMN2,COLUMN3) VALUES(:COLUMN1,:COLUMN2,:COLUMN3) ";                    
                 for (int j = 0; j < dt.Columns.Count; j++)
                 {
                     colValue.Add(dt.Rows[i][j].ToString());
                 }                     
                 objDAL.InsertWithParams(finalSql,colValue,cols, out error);
                 if (error != "")
                     return error;
                 inserts++;
                 colValue.Clear();
            }
        }
        

        下面给出InsertWithParams

        public string InsertWithParams(string sql, List<string> colValue, List<string> cols, out string error)
        {
             error = "";
             try
             {
                 OracleConnection con = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=)(PORT=)))(CONNECT_DATA=(SERVER=DEDICATED)(SID=)));User Id=;Password="); 
                 OracleCommand command = new OracleCommand(sql, con);
                 for (int i = 0; i < colValue.Count; i++)
                 {
                      command.Parameters.Add(new OracleParameter(cols[i], colValue[i]));
                 }
                 command.ExecuteNonQuery();
                 command.Connection.Close();
            }
            catch (Exception ex)
            {
                 error = ex.Message;
            }
            return null;
        }
        

        【讨论】:

          【解决方案6】:
                        try  {
          
                              //Suppose you have DataTable dt
                              string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
                                                        @"Data Source='Give path of your access database file here';Persist Security Info=False";
          
                              OleDbConnection dbConn = new OleDbConnection(connectionString);
                              dbConn.Open();
                              using (dbConn)
                              {
                                  int j = 0;
                                  for (int i = 0; i < 2; i++)
                                  {
                                      OleDbCommand cmd = new OleDbCommand(
                                      "INSERT INTO Participant_Profile ([column1], [column2] , [column3] ) VALUES (@c1 , @c2 , @c3 )", dbConn);
                                      cmd.Parameters.AddWithValue("@c1", dt.rows[i][j].ToString());
                                      cmd.Parameters.AddWithValue("@c2", dt.rows[i][j].ToString());
                                      cmd.Parameters.AddWithValue("@c3", dt.rows[i][j].ToString());
                                      cmd.ExecuteNonQuery();
                                      j++;
                                  }
          
          
          
                              }
                          }
                          catch (OleDbException exception)
                          {
                              Console.WriteLine("SQL Error occured: " + exception);
                          }
          

          【讨论】:

            【解决方案7】:

            我知道这件事很WHILE,但我也遇到了同样的需求:“将数据从数据表插入到 Oracle 表”。我找到了这个线程。我也尝试了答案,得出的结论是执行一个

            ...
            cmd.ExecuteNonQuery();
            ...
            

            在一个循环中,很糟糕。真的很糟糕。不好的第一件事是性能,第二是不必要的复杂性,第三是不必要的 Oracle 对象(存储过程)。完成(比如说 200 行)所需的时间几乎是 1 分钟,这就是我将其四舍五入。因此,希望其他人会发现这对我有帮助,这是我的经验。

            我很固执,又找了一些,所以我发现this,确实是2018年的。但我自己也在2021年......

            所以基本代码是:

            using Oracle.ManagedDataAccess.Client; // you don't need other dll, just install this from nuget gallery
            using System.Data;
            public static void Datatable2Oracle(string tableName, DataTable dataTable)
            {
                string connString = "connection string";
                OracleBulkCopy copy= new(connString, OracleBulkCopyOptions.UseInternalTransaction /*I don't know what this option does*/);
                copy.DestinationTableName = tableName; 
                copy.WriteToServer(dataTable);
                copy.Dispose();
            }
            

            这应该与原始的 oracle DDL 性能相匹配:

            create table table_name as select * from other_table_name
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-08-04
              • 2019-02-25
              • 2021-02-27
              • 1970-01-01
              • 2013-10-17
              相关资源
              最近更新 更多