2017-07-24 120 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