webentwicklung-frage-antwort-db.com.de

Wie füge ich eine Datentabelle in die SQL Server-Datenbanktabelle ein?

Ich habe Daten aus einer Excel-Datei importiert und in einer datatable gespeichert. Jetzt möchte ich diese Informationen in meiner SQL Server-Datenbank speichern.

Ich habe viele Informationen im Internet gesehen, kann sie aber nicht verstehen:

  1. Jemand sagte Zeile für Zeile einfügen ein anderes vorgeschlagenes Massenupdate ... usw.: Was ist besser?
  2. Soll ich OLE- oder SQL Server-Objekte verwenden (wie dataAdapter oder connection)?

Ich muss den wöchentlichen Stundenbericht des Mitarbeiters aus seiner Excel-Datei lesen und in einer Datenbanktabelle speichern, in der alle Berichte gespeichert werden (Aktualisierung der Datenbank mit neuen Datensätzen jede Woche).

Die Excel-Datei enthält nur Berichte für die aktuelle Woche.

40
Asaf Gilad

Erstellen Sie einen User-Defined TableType in Ihrer Datenbank:

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

und definieren Sie einen Parameter in Ihrem Stored Procedure:

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

und sende deine DataTable direkt an den SQL Server:

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);
}

Um die Werte in gespeicherter Prozedur zu bearbeiten, können Sie eine lokale Variable mit demselben Typ deklarieren und eine Eingabetabelle einfügen:

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

Dann können Sie @modifiableTableType bearbeiten:

UPDATE @modifiableTableType SET [Name] = 'new value'
59
Navid Farhadi

Wenn es das erste Mal ist, dass Sie Ihre Daten speichern können

Tun Sie dies (mit Massenkopie). Stellen Sie sicher, dass keine PK/FK-Einschränkung vorliegt

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);
} 

Jetzt haben Sie bereits einen Grundeintrag. Und Sie möchten nur den neuen Datensatz mit dem vorhandenen überprüfen. Sie können das einfach tun.

Dies führt im Wesentlichen dazu, dass vorhandene Tabellen aus der Datenbank übernommen werden

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);

Übergeben Sie dann diese Tabelle an diese Funktion

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;
}

Dadurch wird eine neue DataTable mit den geänderten Zeilen zurückgegeben. Bitte stellen Sie sicher, dass Sie die Funktion korrekt aufrufen. Die DataTable soll zuerst die neueste sein.

Wiederholen Sie dann die Bulkcopy-Funktion noch einmal mit dieser neuen Datentabelle.

20
rofans91

Ich gebe einen sehr einfachen Code, den ich in meiner Lösung verwendet habe (ich habe die gleiche Problemstellung wie Ihre).

    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();

Ich habe einen vordefinierten Tabellennamen als "abcd" angegeben (Sie müssen darauf achten, dass eine Tabelle mit diesem Namen nicht in Ihrer Datenbank vorhanden ist) . :)

7
Luv

Ich würde vorschlagen, dass Sie sich für Masseneinfügung entscheiden, wie in diesem Artikel vorgeschlagen: Masseneinfügung von Daten mithilfe von C # DataTable und SQL Server OpenXML-Funktion

4
Pranay Rana
    //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")
0
masoud Cheragee
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;
} 
0
sachin

Ich habe festgestellt, dass es besser ist, Zeile für Zeile zur Tabelle hinzuzufügen, wenn Ihre Tabelle einen Primärschlüssel hat. Wenn Sie die gesamte Tabelle auf einmal einfügen, wird ein Konflikt beim automatischen Inkrement erzeugt. 

Hier ist meine gespeicherte Proc

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

Ich füge diesen Code in einer Schleife für jede Zeile ein, die ich meiner Tabelle hinzufügen muss:

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

Und hier ist mein Data Access Layer-Code:

        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();
        }

    }
0
jade290