从oracle10g将包含clob字段的数据导入oracle 9i

今天从oracle10g将包含clob字段的数据导入oracle 9i中,在网上搜到的方法是说从9i的客户端导出的bmp文件可以直接导入9i的数据库,但试了N次都没成功,最后只好自己动手写代码导,现将主要思路公布:


思路:

先生成建表的语句,然后自己写代码来实现生成insert语句和执行insert语句的功能。


具体步骤如下:

一、进入pl/sql,将高版本的数据库的表导出(因为表中包含了clob类型的字段,所以用pl/sql导出insert语句的时候没法导出)


二、写代码生成insert语句

首先用select table_name from user_tables语句查询表空间中的所有用户表的表名

SqlLib DoSql = new SqlLib();//SqlLib类自己实现吧,其实就是一个数据库操作类,其中的DoExecuteSqlString方法用来执行sql语句并返回datatable类型的数据

DataTable tnames = DoSql.DoExecuteSqlString("select table_name,num_rows from user_tables");


接下来循环生成所有表的insert语句

1)查询指定表的所有字段以及字段的数据类型

2)查询表的所有数据

for (int i = 0; i < tnames.Rows.Count; i++)//循环所有表
{

//查询指定表的所有字段以及字段的数据类型

DataTable tclos = DoSql.DoExecuteSqlString("select t.table_name,t.column_name,t.data_type,c.COMMENTS from user_tab_columns t,user_col_comments c where t.table_name = c.table_name and t.column_name = c.column_name and t.table_name = '" + SqlLib.GetString(tnames.Rows[i]["table_name"]) + "'");

//查询该表的所有数据
 DataTable dbList = DoSql.DoExecuteSqlString("select * from " + SqlLib.GetString(tnames.Rows[i]["table_name"]));

//这里生成insert语句

}

3)生成inert语句

StringBuilder sb = new StringBuilder();

for (int db = 0; db < dbList.Rows.Count; db++)
 {
      sb.Append("insert into " + SqlLib.GetString(tnames.Rows[i]["table_name"]) + "(");
       for (int c = 0; c < tclos.Rows.Count; c++)
       {
           if (c > 0)
               sb.Append("," + SqlLib.GetString(tclos.Rows[c]["column_name"]));
            else
               sb.Append(SqlLib.GetString(tclos.Rows[c]["column_name"]));
        }
   sb.Append(")values(");

   for (int c = 0; c < tclos.Rows.Count; c++)
    {

        string dbtype = SqlLib.GetString(tclos.Rows[c]["data_type"]).ToUpper();

        if (c > 0) sb.Append( ",");

switch (dbtype)
                            {
                                case "NUMBER":
                                    sb.Append(SqlLib.GetString(dbList.Rows[db][SqlLib.GetString(tclos.Rows[c]["column_name"])]));
                                    break;
                                case "DATE":
                                   sb.Append("'" + SqlLib.GetString(dbList.Rows[db][SqlLib.GetString(tclos.Rows[c]["column_name"])]) + "'");
                                    break;
                                case "CLOB":
                                    sb.Append("$$$_____$$$【@" + SqlLib.GetString(tclos.Rows[c]["column_name"]) + "@C@'" + SqlLib.GetString(dbList.Rows[db][SqlLib.GetString(tclos.Rows[c]["column_name"])]) + "'】$$$_____$$$");
                                    break;
                                default:
                                    sb.Append("$$$_____$$$【@" + SqlLib.GetString(tclos.Rows[c]["column_name"]) + "@V@'" + SqlLib.GetString(dbList.Rows[db][SqlLib.GetString(tclos.Rows[c]["column_name"])]) + "'】$$$_____$$$");
                                    break;
                            }

      }

   sb.Append(");\n----------------------------------------\n\r\n\r\n\r");

}

Utils.WriteText(Utils.GetMapPath("/test.sql"), sb.ToString());//将生成的insert语句写入文本,这里的Utils.WriteText方法即为将制定内容写入文本文件的代码,具体代码请实现


其中的“$$$_____$$$【@字段名@数据类型@'数据内容'】$$$_____$$$"是为了让导入程序提取字段名、数据类型、数据内容而设置的特殊符号

”;\n----------------------------------------\n\r\n\r\n\r“是为了让导入程序识别单一的一条insert语句的结尾


三、写一个导入数据的程序

步骤二说明了如何生成insert语句,这一步说明如何识别步骤二生成的insert语句并导入数据库

1)读取步骤二生成的test.sql文件

string html = Utils.LoadFile(Utils.GetMapPath("/test.sql")).Trim();//读取test.sql,Utils.LoadFile方法请实现

string[] arr = Utils.SplitString(html, ";\n----------------------------------------\n\r\n\r\n\r");//每条insert语句作为数组的一个元素

下面贴出 Utils.SplitString方法的定义

        public static string[] SplitString(string strContent, string strSplit)
        {
            if (strContent.IndexOf(strSplit) < 0)
            {
                string[] tmp = { strContent };
                return tmp;
            }
            if (strContent == null || strContent == "")
            {
                string[] tmp = { strContent };
                return tmp;
            }
            RegexOptions options;
            if (Environment.Version.Major == 1)
                options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline;
            else
                options = RegexOptions.IgnoreCase | RegexOptions.Singleline;
            return Regex.Split(strContent, @strSplit, options);
        }

2)开始拼接sql语句

List<string> sqlList = new List<string>();//sql语句

Regex r = null;Match m = null;

string rpt = @"\$\$\$_____\$\$\$【@([^@]+)@([^@]+)@'([\s\S]*?)'】\$\$\$_____\$\$\$";//用正则式来识别字段名、数据类型、数据内容

RegexOptions options;
 if (Environment.Version.Major == 1)
      options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline;
else
     options = RegexOptions.IgnoreCase | RegexOptions.Singleline;

//开始拼接

for (int i = 0; i < arr.Length; i++)
{

因为Utils.LoadFile(Utils.GetMapPath("/test.sql")).Trim();将最后的\n\r\n\r\n\r去掉了,所以下面的一句是为了去掉最后面的;\n----------------------------------------
  string val = arr[i].Replace(";\n----------------------------------------", "").Trim();
                    ArrayList spArray = new ArrayList();//用来存储每条sql语句的OracleParameter参数
                    r = new Regex(rpt, options);
                    for (m = r.Match(arr[i]); m.Success; m = m.NextMatch())
                    {
                        string __type = m.Groups[2].ToString();//数据类型
                        string __tem = m.Groups[3].ToString();//数据内容
                        if (__type == "C")
                        {//C表示CLOB
                            if (__tem == "")
                                __tem = "&nbsp;";//因为CLOB无法插入空字串,因此插入一个html的空格

                            //DoSql.CreateParameter方法是创建一个OracleParameter对象,具体代码请实现
                            spArray.Add(DoSql.CreateParameter(":" + m.Groups[1].ToString(), OracleType.Clob, __tem));
                        }
                        else if (__type == "V")
                        {//V表示VARCHAR类型

                            spArray.Add(DoSql.CreateParameter(":" + m.Groups[1].ToString(), OracleType.VarChar, __tem));
                        }
                    }
                    sqlList.Add(Regex.Replace(val, rpt, ":$1"));
                    spList.Add(spArray);
}

程序执行到这里就已经生成了可以执行的sql语句

其中sqlList是一个泛型,泛型的每个元素为一条sql语句

spList是一个ArrayList 类型(ArrayList 的单个元素依然是ArrayList 类型),其中的每个元素对应泛型中某条sql语句的OracleParameter参数

编写一个执行事务的方法去执行这些sql语句即可实现导入功能

if (DoSql.DoTransaction(sqlList, spList) > 0)
{
    base.Alert("数据导入成功 ^_^", "default.aspx");
 }else{
    base.Alert("系统错误,无法完成导入", "default.aspx");
}

        #region 执行事务
        public int DoTransaction(List<string> sqlString, List<ArrayList> spList)
        {
            int result = 0;
            this.CreateConn();//CreateConn方法请实现,下面的代码并不能直接运行,仅供参考

            OracleTransaction st = this.conn.BeginTransaction(IsolationLevel.Serializable);
            try
            {
                for (int i = 0; i < sqlString.Count; i++)
                {
                    this.comm = new OracleCommand(sqlString[i], this.conn, st);
                    this.comm.CommandType = CommandType.Text;
                    if (spList != null && spList.Count > i)
                    {
                        OracleParameter[] oparams = (OracleParameter[])spList[i].ToArray(typeof(OracleParameter));
                        for (int k = 0; k < oparams.Length; k++)
                        {
                            this.comm.Parameters.Add(oparams[k]);
                        }
                    }
                    result = this.comm.ExecuteNonQuery();
                    this.comm.Dispose();
                }
                //result = Convert.ToInt32(this.comm.ExecuteScalar());
                st.Commit();
            }
            catch (Exception)
            {
                result = 0;
                st.Rollback();
            }
            finally
            {
                st.Dispose();
            }
            this.Close();
            return result;
        }
        public int DoTransaction(List<string> sqlString)
        {
            return DoTransaction(sqlString, null);
        }
        #endregion

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值