在数据库之间复制表

时间:2017-07-24 11:21:24

标签: c# sql-server database sqlconnection smo

假设我想将所有表格及其完整数据从一个数据库复制到另一个数据库,而无需具体了解有关它们的详细信息(列数,数据类型......)。用户将连接字符串输入到他的数据库,并将其中的所有数据复制到内部数据库。 我试图通过使用SqlConnection并编写直接的T-SQL查询来实现它,并设法编写一个脚本,在内部数据库中使用正确的列创建空表:

string createDestinationTableQuery = "create table " + schemaName + ".[" + tableName + "](";
DataTable ColumnsDT = new DataTable();
string getTableColumnDataQuery = "SELECT * FROM "+originalDBName+".INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'" + tableName +"'";
SqlCommand getTableColumnDataCommand = new SqlCommand(getTableColumnDataQuery, originalCon);
SqlDataAdapter TableDA = new SqlDataAdapter(getTableColumnDataCommand);
TableDA.Fill(ColumnsDT);
for (int x = 0; x < ColumnsDT.Rows.Count; x++)
{
    createDestinationTableQuery += "[" + ColumnsDT.Rows[x].ItemArray[3].ToString() + "] " + "[" + ColumnsDT.Rows[x].ItemArray[7].ToString() + "], ";

}

createDestinationTableQuery = createDestinationTableQuery.Remove(createDestinationTableQuery.Length - 2);
createDestinationTableQuery += " )";

SqlCommand createDestinationTableCommand = new SqlCommand(createDestinationTableQuery, destinationCon);
createDestinationTableCommand.ExecuteNonQuery();
Console.WriteLine("Table " + schemaName + "." + tableName + " created succesfully!");

但是,我正在努力处理数据插入,因为以下代码根本不起作用:

DataTable dataTable = new DataTable();

string getTableDataquery = "select * from " + originalTableWithSchema;
SqlCommand getTableDataCommand = new SqlCommand(getTableDataquery, originalCon);
SqlDataAdapter da = new SqlDataAdapter(getTableDataCommand);

da.Fill(dataTable);

for (int x = 0; x < dataTable.Rows.Count; x++)
{
    string insertQuery = "insert into " + schemaName + ".["+tableName+"](" ;
    string values = "VALUES(";

    for (int y = 0; y < dataTable.Columns.Count; y++)
    {
        insertQuery += dataTable.Columns[y].ColumnName + ", ";
        values += dataTable.Rows[x].ItemArray[y].ToString() + ", ";
    }
    insertQuery = insertQuery.Remove(insertQuery.Length - 2);
    insertQuery += " )";
    values = values.Remove(values.Length - 2);
    values += " )";
    insertQuery += " " + values;
    SqlCommand insertCommand = new SqlCommand(insertQuery, destinationCon);
    insertCommand.ExecuteNonQuery();

}

da.Dispose();

如何正确实现此功能?我在考虑废弃所有代码并使用SMO代替?

2 个答案:

答案 0 :(得分:2)

如果您只想复制数据(因为您已经创建了结构),那么您可以使用DataTable将数据保存在非dbms特定结构中,并使用DataAdapter生成特定于dbms的insert语句。以下是我前一段时间编写的代码摘录,用于将数据从Access复制到MySQL:

List<string> tableNames = new List<string>();
try
{
    // Open connect to access db
    sourceConn.Open();
    // Build table names list from schema
    foreach (DataRow row in sourceConn.GetSchema("Tables").Select("table_type = 'TABLE'"))
        tableNames.Add(row["table_name"].ToString());                
}
catch (Exception ex)
{
    throw ex;
}
finally
{
    if(sourceConn.State != ConnectionState.Closed)
        sourceConn.Close();
}

foreach (string table in tableNames)
{
    //Get all table data from Access
    string query = string.Format("SELECT * FROM {0}", table);
    DataTable accessTable = new DataTable(table);
    try
    {
        sourceConn.Open();
        System.Data.OleDb.OleDbCommand accessSqlCommand = new System.Data.OleDb.OleDbCommand(query, accessConn);
        System.Data.OleDb.OleDbDataReader reader = (System.Data.OleDb.OleDbDataReader)accessSqlCommand.ExecuteReader();
        // Load all table data into accessTable
        accessTable.Load(reader);
    }
    catch(Exception ex)
    {
        throw ex;
    }
    finally
    {
        if(sourceConn.State != ConnectionState.Closed)
            sourceConn.Close();
    }

    // Import data into MySQL
    accessTable.AcceptChanges();
    // The table should be empty, so set everything as new rows (will be inserted)
    foreach (DataRow row in accessTable.Rows)
        row.SetAdded();

    try
    {
        destConn.Open();
        MySql.Data.MySqlClient.MySqlDataAdapter da = new MySql.Data.MySqlClient.MySqlDataAdapter(query, mySqlConn);
        MySql.Data.MySqlClient.MySqlCommandBuilder cb = new MySql.Data.MySqlClient.MySqlCommandBuilder(da);
        da.InsertCommand = cb.GetInsertCommand();

        // Update the destination table 128 rows at a time
        da.UpdateBatchSize = 128;

        // Perform inserts (and capture row counts for output)
        int insertCount = da.Update(accessTable);
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        if(destConn.State != ConnectionState.Closed)
            destConn.Close();
    }
}

这当然可以更有效率,但我写它是为了快速转换。此外,由于这是复制和粘贴,您可能需要调整它。希望它有所帮助。

答案 1 :(得分:0)

使用链接服务器可能值得考虑。在目标服务器中定义链接服务器后,可以使用SELECT…INTO语句创建表并自动填充数据。

在目标服务器数据库中执行的查询:

SELECT * INTO NewTableName FROM 
SourceServername.SourceDatabasename.dbo.SourceTableName