¿Cómo insertar una tabla de datos en la tabla de la base de datos de SQL Server?

He importado datos de algún archivo de Excel y los he guardado en una datatable . Ahora me gustaría guardar esta información en mi base de datos de SQL Server .

Vi mucha información en la web pero no puedo entenderla:

  1. Alguien dijo insertar línea por línea otra actualización masiva sugerida … etc: ¿qué mejor?
  2. ¿Debería usar objetos OLE o SQL Server (como dataAdapter o connection )?

Mi necesidad es leer el informe de horas semanales de los empleados, desde su archivo Excel y guardarlo en una tabla de la base de datos donde se guardan todos los informes (actualizando el db con nuevos registros cada semana).

El archivo de Excel contiene informes solo para la semana actual.

Cree un User-Defined TableType en su base de datos:

 CREATE TYPE [dbo].[MyTableType] AS TABLE( [Id] int NOT NULL, [Name] [nvarchar](128) NULL ) 

y define un parámetro en su Stored Procedure :

 CREATE PROCEDURE [dbo].[InsertTable] @myTableType MyTableType readonly AS BEGIN insert into [dbo].Records select * from @myTableType END 

y envíe su DataTable directamente al servidor sql:

 using (var command = new SqlCommand("InsertTable") {CommandType = CommandType.StoredProcedure}) { var dt = new DataTable(); //create your own data table command.Parameters.Add(new SqlParameter("@myTableType", dt)); SqlHelper.Exec(command); } 

Para editar los valores dentro de stored-procedure, puede declarar una variable local con el mismo tipo e insertar una tabla de entrada en ella:

 DECLARE @modifiableTableType MyTableType INSERT INTO @modifiableTableType SELECT * FROM @myTableType 

Luego, puede editar @modifiableTableType :

 UPDATE @modifiableTableType SET [Name] = 'new value' 

Si es la primera vez que guardas tu tabla de datos

Haz esto (usando una copia masiva). Asegúrate de que no haya restricciones PK / FK

 SqlBulkCopy bulkcopy = new SqlBulkCopy(myConnection); //I assume you have created the table previously //Someone else here already showed how bulkcopy.DestinationTableName = table.TableName; try { bulkcopy.WriteToServer(table); } catch(Exception e) { messagebox.show(e.message); } 

Ahora que ya tienes un registro básico. Y solo quiere comprobar el nuevo registro con el existente. Simplemente puede hacer esto.

Esto básicamente tomará la tabla existente de la base de datos

 DataTable Table = new DataTable(); SqlConnection Connection = new SqlConnection("ConnectionString"); //I assume you know better what is your connection string SqlDataAdapter adapter = new SqlDataAdapter("Select * from " + TableName, Connection); adapter.Fill(Table); 

Luego pasa esta tabla a esta función

 public DataTable CompareDataTables(DataTable first, DataTable second) { first.TableName = "FirstTable"; second.TableName = "SecondTable"; DataTable table = new DataTable("Difference"); try { using (DataSet ds = new DataSet()) { ds.Tables.AddRange(new DataTable[] { first.Copy(), second.Copy() }); DataColumn[] firstcolumns = new DataColumn[ds.Tables[0].Columns.Count]; for (int i = 0; i < firstcolumns.Length; i++) { firstcolumns[i] = ds.Tables[0].Columns[i]; } DataColumn[] secondcolumns = new DataColumn[ds.Table[1].Columns.Count]; for (int i = 0; i < secondcolumns.Length; i++) { secondcolumns[i] = ds.Tables[1].Columns[i]; } DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false); ds.Relations.Add(r); for (int i = 0; i < first.Columns.Count; i++) { table.Columns.Add(first.Columns[i].ColumnName, first.Columns[i].DataType); } table.BeginLoadData(); foreach (DataRow parentrow in ds.Tables[0].Rows) { DataRow[] childrows = parentrow.GetChildRows(r); if (childrows == null || childrows.Length == 0) table.LoadDataRow(parentrow.ItemArray, true); } table.EndLoadData(); } } catch (Exception ex) { throw ex; } return table; } 

Esto devolverá una nueva DataTable con las filas modificadas actualizadas. Por favor, asegúrese de llamar a la función correctamente. La DataTable primero se supone que es la última.

Luego repita la función de bulkcopy todo de nuevo con esta nueva tabla de datos.

Le doy un código muy simple, que utilicé en mi solución (tengo el mismo problema que el tuyo)

  SqlConnection con = connection string ; //new SqlConnection("Data Source=.;uid=sa;pwd=sa123;database=Example1"); con.Open(); string sql = "Create Table abcd ("; foreach (DataColumn column in dt.Columns) { sql += "[" + column.ColumnName + "] " + "nvarchar(50)" + ","; } sql = sql.TrimEnd(new char[] { ',' }) + ")"; SqlCommand cmd = new SqlCommand(sql, con); SqlDataAdapter da = new SqlDataAdapter(cmd); cmd.ExecuteNonQuery(); using (var adapter = new SqlDataAdapter("SELECT * FROM abcd", con)) using(var builder = new SqlCommandBuilder(adapter)) { adapter.InsertCommand = builder.GetInsertCommand(); adapter.Update(dt); // adapter.Update(ds.Tables[0]); (Incase u have a data-set) } con.Close(); 

He dado un nombre de tabla predefinido como “abcd” (debe tener cuidado de que una tabla con este nombre no exista en su base de datos). Por favor, vote mi respuesta si funciona para usted. 🙂

Le sugiero que vaya a la inserción masiva como se sugiere en este artículo: Inserción masiva de datos mediante la función C # DataTable y la función OpenXML del servidor SQL.

 public bool BulkCopy(ExcelToSqlBo objExcelToSqlBo, DataTable dt, SqlConnection conn, SqlTransaction tx) { int check = 0; bool result = false; string getInsert = ""; try { if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { if (dr != null) { if (check == 0) { getInsert = "INSERT INTO [tblTemp]([firstName],[lastName],[Father],[Mother],[Category]" + ",[sub_1],[sub_LG2])"+ " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString(); check += 1; } else { getInsert += " UNION ALL "; getInsert += " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString() ; check++; } } } result = common.ExecuteNonQuery(getInsert, DatabasesName, conn, tx); } else { throw new Exception("No row for insertion"); } dt.Dispose(); } catch (Exception ex) { dt.Dispose(); throw new Exception("Please attach file in Proper format."); } return result; } 
  //best way to deal with this is sqlbulkcopy //but if you dont like it you can do it like this //read current sql table in an adapter //add rows of datatable , I have mentioned a simple way of it //and finally updating changes Dim cnn As New SqlConnection("connection string") cnn.Open() Dim cmd As New SqlCommand("select * from sql_server_table", cnn) Dim da As New SqlDataAdapter(cmd) Dim ds As New DataSet() da.Fill(ds, "sql_server_table") Dim cb As New SqlCommandBuilder(da) //for each datatable row ds.Tables("sql_server_table").Rows.Add(COl1, COl2) da.Update(ds, "sql_server_table") 

Descubrí que era mejor agregar a la tabla fila por fila si su tabla tiene una clave principal. Insertar toda la tabla de una vez crea un conflicto en el incremento automático.

Aquí está mi Proc almacenado

 CREATE PROCEDURE dbo.usp_InsertRowsIntoTable @Year int, @TeamName nvarchar(50), AS INSERT INTO [dbo.TeamOverview] (Year,TeamName) VALUES (@Year, @TeamName); RETURN 

Puse este código en un bucle por cada fila que necesito agregar a mi tabla:

 insertRowbyRowIntoTable(Convert.ToInt16(ddlChooseYear.SelectedValue), name); 

Y aquí está mi código de capa de acceso a datos:

  public void insertRowbyRowIntoTable(int ddlValue, string name) { SqlConnection cnTemp = null; string spName = null; SqlCommand sqlCmdInsert = null; try { cnTemp = helper.GetConnection(); using (SqlConnection connection = cnTemp) { if (cnTemp.State != ConnectionState.Open) cnTemp.Open(); using (sqlCmdInsert = new SqlCommand(spName, cnTemp)) { spName = "dbo.usp_InsertRowsIntoOverview"; sqlCmdInsert = new SqlCommand(spName, cnTemp); sqlCmdInsert.CommandType = CommandType.StoredProcedure; sqlCmdInsert.Parameters.AddWithValue("@Year", ddlValue); sqlCmdInsert.Parameters.AddWithValue("@TeamName", name); sqlCmdInsert.ExecuteNonQuery(); } } } catch (Exception ex) { throw ex; } finally { if (sqlCmdInsert != null) sqlCmdInsert.Dispose(); if (cnTemp.State == ConnectionState.Open) cnTemp.Close(); } } 

Desde mi comprensión de la pregunta, esto puede usar una solución bastante directa. De todos modos, a continuación se muestra el método que propongo, este método toma una tabla de datos y luego utiliza sentencias de SQL para insertarlas en una tabla de la base de datos. Tenga en cuenta que mi solución está utilizando MySQLConnection y MySqlCommand reemplazarlo con SqlConnection y SqlCommand.

 public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat) { for (int i = 0; i < tblFormat.Rows.Count; i++) { String InsertQuery = string.Empty; InsertQuery = "INSERT INTO customercredit " + "(ACCOUNT_CODE,NAME,CURRENCY,CREDIT_LIMIT) " + "VALUES ('" + tblFormat.Rows[i]["AccountCode"].ToString() + "','" + tblFormat.Rows[i]["Name"].ToString() + "','" + tblFormat.Rows[i]["Currency"].ToString() + "','" + tblFormat.Rows[i]["CreditLimit"].ToString() + "')"; using (MySqlConnection destinationConnection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString())) using (var dbcm = new MySqlCommand(InsertQuery, destinationConnection)) { destinationConnection.Open(); dbcm.ExecuteNonQuery(); } } }//CreditLimit