2017-07-24 116 views
1

假设我想将所有表格及其完整数据从一个数据库复制到另一个数据库,而不需要特别了解有关它们的详细信息(列数,数据类型...)。用户可以将连接字符串输入到他的数据库中,并将所有数据复制到内部数据库中。 我试图用的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?

+0

'代码根本不起作用:'这是什么意思?你调试了代码吗?你遇到的任何错误? –

回答

2

如果您只想复制数据(因为您的结构创建已经在工作),那么您可以使用DataTable将数据保存在非dbms特定结构中,并使用DataAdapter生成dbms特定插入语句。下面是从代码我写了一段时间前将数据从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

@UweKeim我同意。我怀疑他们正在使用这种反模式,因此他们总是关闭连接。 OP - 更好的方法是将你的连接包装在USING语句中。 –

+0

@SeanLange或者至少,使用'try ... finally',没有(在上面的代码中使用堆栈)'throw'。 –

0

这可能值得考虑使用链接服务器。一旦在目标服务器中定义了链接服务器,就可以创建一个表并使用SELECT…INTO语句自动填充数据。在目标服务器数据库中执行

查询:

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