zoukankan      html  css  js  c++  java
  • Oracle中对超长内容的处理,避免出现can bind a LONG value only for insert into a LONG column错误

    本人在做一个新闻内容的模块的时候,发现如果内容在4K以上的字符串会出错,得到的内容会是乱码(也就是被自动截断),如果小于4K,那么就不会有问题。

    原来采用了Varchar2的类型来存储,但发现后修改为Clob类型的也出现同样的问题,而且发现日志的错误是:System.Data.OracleClient.OracleException: ORA-01461: can bind a LONG value only for insert into a LONG column。

    由于Clob类型是可以存放很大类型的文本数据的,不会是数据库字段容量不够,因此检查插入和更新的C#代码,发现原来的代码是这样的:

     代码

            public bool Insert(Hashtable recordField, string targetTable, DbTransaction trans)
            {
                
    bool result = false;
                
    string fields = ""// 字段名
                string vals = ""// 字段值
                if ( recordField == null || recordField.Count < 1 )
                {
                    
    return result;
                }

                List
    <OracleParameter> paramList = new List<OracleParameter>();
                IEnumerator eKeys 
    = recordField.Keys.GetEnumerator();

                
    while ( eKeys.MoveNext() )
                {
                    
    string field = eKeys.Current.ToString();
                    fields 
    += field + ",";
                    
    if (!string.IsNullOrEmpty(seqField) && !string.IsNullOrEmpty(seqName)
                        
    && (field.ToUpper() == seqField.ToUpper()))
                    {
                        vals 
    += string.Format("{0}.NextVal,", seqName);
                    }
                    
    else
                    {
                        vals 
    += string.Format(":{0},", field);
                        
    object val = recordField[eKeys.Current.ToString()];
                        paramList.Add(
    new OracleParameter(":" + field, val));
                    }
                }

                fields 
    = fields.Trim(',');//除去前后的逗号
                vals = vals.Trim(',');//除去前后的逗号
                string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", targetTable, fields, vals);

                Database db 
    = DatabaseFactory.CreateDatabase();
                DbCommand command 
    = db.GetSqlStringCommand(sql);
                command.Parameters.AddRange(paramList.ToArray());

                
    if ( trans != null )
                {
                    result 
    = db.ExecuteNonQuery(command, trans) > 0;
                }
                
    else
                {
                    result 
    = db.ExecuteNonQuery(command) > 0;
                }

                
    return result;
            }

     重要的地方就是我使用了该行代码:

    paramList.Add(new OracleParameter(":" + field, val));

    猜想可能是由于这行代码的问题导致,因此修改参数化的Oracle参数变量代码为另外一个种指定对象类型的方式:

    OracleParameter a = new OracleParameter(":" + field, OracleType.Clob, val.ToString().Length);
                            a.Value 
    = val;
                            paramList.Add(a);

    验证通过,发现再长的内容,写入也是正常的,不会出错和出现的截断乱码。由于第一种忽略了Oracle参数类型,就是为了适应各种类型对象的参数化构造,实现统一添加参数化内容的,由于超长的字符内容会出现问题,因此只好修改基类操作的添加参数代码,添加一个条件分支作为处理。调整后的插入代码如下(更新代码类似操作):

     代码

            public bool Insert(Hashtable recordField, string targetTable, DbTransaction trans)
            {
                
    bool result = false;
                
    string fields = ""// 字段名
                string vals = ""// 字段值
                if ( recordField == null || recordField.Count < 1 )
                {
                    
    return result;
                }

                List
    <OracleParameter> paramList = new List<OracleParameter>();
                IEnumerator eKeys 
    = recordField.Keys.GetEnumerator();

                
    while ( eKeys.MoveNext() )
                {
                    
    string field = eKeys.Current.ToString();
                    fields 
    += field + ",";
                    
    if (!string.IsNullOrEmpty(seqField) && !string.IsNullOrEmpty(seqName)
                        
    && (field.ToUpper() == seqField.ToUpper()))
                    {
                        vals 
    += string.Format("{0}.NextVal,", seqName);
                    }
                    
    else
                    {
                        vals 
    += string.Format(":{0},", field);
                        
    object val = recordField[eKeys.Current.ToString()];

                        
    if (val.ToString().Length >= 4000)
                        {
                            OracleParameter a 
    = new OracleParameter(":" + field, OracleType.Clob, val.ToString().Length);
                            a.Value 
    = val;
                            paramList.Add(a);
                        }
                        
    else
                        {
                            paramList.Add(
    new OracleParameter(":" + field, val));
                        }
                    }
                }

                fields 
    = fields.Trim(',');//除去前后的逗号
                vals = vals.Trim(',');//除去前后的逗号
                string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", targetTable, fields, vals);

                Database db 
    = DatabaseFactory.CreateDatabase();
                DbCommand command 
    = db.GetSqlStringCommand(sql);
                command.Parameters.AddRange(paramList.ToArray());

                
    if ( trans != null )
                {
                    result 
    = db.ExecuteNonQuery(command, trans) > 0;
                }
                
    else
                {
                    result 
    = db.ExecuteNonQuery(command) > 0;
                }

                
    return result;
            }

     这样,就可以在使用代码生成工具Database2Sharp(http://www.iqidi.com/database2sharp.htm)生成的Oracle代码中,不需要改变任何地方,只需要调整BaseDAL的基类中Insert和Update中的部分内容,就可以了。

    主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
    专注于Winform开发框架/混合式开发框架Web开发框架Bootstrap开发框架微信门户开发框架的研究及应用
      转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com 
        
  • 相关阅读:
    linux查看CPU和内存信息
    linux yum命令详解
    查看文件中关键字前后几行的内容
    vue.js+web storm安装及第一个vue.js
    android GPS: code should explicitly check to see if permission is available
    ASP.NET MVC Identity 使用自己的SQL Server数据库
    阿里云服务器,tomcat启动,一直卡在At least one JAR was scanned for TLDs yet contained no TLDs就不动了
    ASP.NET MVC4 MVC 当前上下文中不存在名称“Scripts”
    python 将windows字体中的汉字生成图片的方法
    Java android DES+Base64加密解密
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/1664140.html
Copyright © 2011-2022 走看看