SqlServer与Oracle之间数据简单转移操作(涉及图片等二进制数组)
公司以前的项目是基于Window系统,使用SqlServer 2005数据库,但最近的项目,考虑到系统的稳定性,安全性,可靠性方面的要求,系统改用Linux,数据库采用Oracle。最近一个项目是在以前项目基础上进行的,并且要把以前的架构按照现有架构进行升级,而数据的安全迁移却是十分重要的,基于这个需求,编写这一个数据迁移程序。记录下来,作为一个记录,同时与大家共同交流。 注:程序使用的前提是目标Oracle中必须提前新建与SqlServer中对应的表结构及约束关系。
虽说网上关于Oracle与SqlServer之间的数据库迁移的文章很多,方法也各异.但是各种复杂的操作与配置对于我来说,并不是十分适用的。对于各种数据迁移方法,大家都有不同的看法,但也许适合的才是最好的吧.程序比较简单,直接贴代码,如果谁有更好方法,不吝献出。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
private void TransDataWithByte()
{
try
{
allCount = 0;//重置统计计数
//用于统计数据字符串表示
StringBuilder staticSb = new StringBuilder();
//开启秒表计时
StartWatch(true);
foreach (string s in tables)
{
//保存表的第一行记录用来取第一个字段
DataTable dtFirst = new DataTable();
StringBuilder sb = new StringBuilder();
List<string> colItems = new List<string>(); //保存每个表的列名
string insert = ""; //存储Insert语句前一段
int rowCount = 0;//保存表中数据条数
int pageSize = Convert.ToInt32(tbxPageSize.Text.Trim());//每页数
int page = 0;//起始页码
int left = 0;//pagesize*(page-1),分页查询中用到
int count = 0;//各表的列数
string firstColName = "";//分布查询中用到
string sqlString = "SELECT Count(*) FROM " + s;
rowCount = Convert.ToInt32(DbHelperMSSQL.GetSingleResult(sqlString));//保存表中数据条数
sqlString = "SELECT top 1 * FROM " + s;
dtFirst = DbHelperMSSQL.Querydt(sqlString);//为了取得表的各列名
if (dtFirst.Rows.Count > 0)
{
//分页查询及更新SQUENCE时要用到
firstColName = dtFirst.Columns[0].ColumnName;
//取得插入的前缀
count = dtFirst.Columns.Count;//保存表的列数,下面构造SQL语句使用
int colCount = 0;
sb.Append("INSERT INTO ");
sb.Append(s + "(");
foreach (DataColumn col in dtFirst.Columns)
{
colCount++;
colItems.Add(col.ColumnName);
if (colCount < count)
{
sb.Append(col.ColumnName + ",");
}
else
{
sb.Append(col.ColumnName);
}
}
sb.Append(") VALUES( ");
insert = sb.ToString();
}
else
{
//表中无数据循环下一张表
continue;
}
//计算页数,每页大小固定500(上面定义好了)
page = Convert.ToInt32(Math.Ceiling(((decimal)rowCount / (decimal)pageSize)));
for (int j = 1; j <= page; j++)
{
//分页查询
StringBuilder pageselect = new StringBuilder();
DataTable dt = new DataTable();
left = pageSize * (j - 1);
pageselect.Append("SELECT TOP (");
pageselect.Append(pageSize);
pageselect.Append(") *");
pageselect.Append(" FROM ");
pageselect.Append(s);
pageselect.Append(" WHERE (");
pageselect.Append(firstColName + " NOT IN ");
pageselect.Append("(SELECT TOP (");
pageselect.Append(left + ") " + firstColName + " FROM " + s + " ORDER BY " + firstColName + "))");
pageselect.Append(" ORDER BY " + firstColName);
dt = DbHelperMSSQL.Querydt(pageselect.ToString());
dt.TableName = s;
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
//i 是在构造下面插入SQL用到,用于判断Values()中插入的项是否是
//最后一项
int i = 0;
//用于保存每一列相关的OracleParameter列表
List<OracleParameter> ops = new List<OracleParameter>();
StringBuilder sbcmd = new StringBuilder();
sbcmd.Append(insert);
foreach (string col in colItems)
{
if (i == count - 1)
{
sbcmd.Append(":" + col);
}
else
{
sbcmd.Append(":" + col + ",");
}
i++;
string paraName = ":" + col;//保存oracleParameter的ParameterName
object o = row[col];
string gt = o.GetType().ToString();
OracleParameter op = new OracleParameter();
op.ParameterName = paraName;
op.Value = o;
ops.Add(op);
}
sbcmd.Append(")");
DbHelperOracle.ExecuteSqlByte(sbcmd.ToString(), ops);
}
}
}
staticSb.Append(s + ":" + rowCount + "条 ");
allCount += rowCount;//保存每张表的数据数之和,用于统计转移数据总数
if (checkSquence)
{
ChangeSuqenceStartValue(s, firstColName);
}
dtFirst = null;
}
//停止秒表,更新状态
StartWatch(false);
Status ea = ShowStatus;
this.Invoke(ea, true, staticSb.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.StackTrace, e.Message);
Status ea = ShowStatus;
this.Invoke(ea, false, "");
return;
}
}
public static DataTable Querydt(string sqlString)
{
using (SqlConnection connection = new SqlConnection(sqlConString))
{
DataTable dt = new DataTable();
try
{
connection.Open();
SqlDataAdapter cmd = new SqlDataAdapter(sqlString, connection);
cmd.Fill(dt);
}
catch (SqlException sq)
{
throw new Exception(sq.Message);
}
return dt;
}
}
public static int ExecuteSqlByte(string oraString, List<OracleParameter> ops)
{
using (OracleConnection connection = new OracleConnection(oracleConString))
{
using (OracleCommand cmd = new OracleCommand(oraString, connection))
{
try
{
cmd.Parameters.AddRange(ops.ToArray());
int rows = cmd.ExecuteNonQuery();
return rows;
}
catch (OracleException e)
{
connection.Close();
throw new Exception("", e);
}
}
}
}
另外,程序效率不是太高,一般的表每秒约130条记录,如果是含有图片等大数据时,每秒大约只有33条左右。在进行数据库的迁移,对于表的顺序是有要求的,一般带有外键约束的表要后导,而如果删除表操作则按照相反的顺序进行。有一个问题要特别注意的,如果遇到一张表没有主键约束,但是在导数据的过程中,如果出现导入混乱造成一张表中存在相同的记录,这在删除时就会比较麻烦(相关删除操作可以搜索一下),所以在导数据时要特别引起注意。
这次导数据也是比较痛苦的,导数据速度不是很快,而数据量也一百几十万,花了不少时间,中间也遇到了一张表中记录重复的,删除也遇到了一点麻烦,因为该表中数据比较大,用网上搜索的删除方法效果都不好,于是直接Trunct,重导,比较痛苦.郑重提醒大家:数据是重要的,须小心谨慎!