使用ODP.Net托管API时,使用数组绑定将数据插入VARCHAR2(4000)类型的列,并且数组中的行值的字符串长度大于1000个字符时,以下异常为抛出:
ORA-01461:只能插入LONG值才能插入LONG列
string sql = "INSERT INTO STAGING(\"COLUMN1\") VALUES (:COLUMN1)";
using (OracleCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
cmd.BindByName = true;
cmd.ArrayBindCount = dt.Rows.Count;
var p = new OracleParameter { ParameterName = parameterName.ToUpper() };
p.OracleDbType = OracleDbType.Varchar2;
p.Value = dt.AsEnumerable().Select(c => (!c.IsNull(fieldName) ? c.Field<T>(fieldName) : default(T))).ToArray();
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
}
我们目前将参数定义为:
p.OracleDbType = OracleDbType.Varchar2;
我尝试使用它,但仍遇到同样的问题:
p.OracleDbType = OracleDbType.Clob;
还尝试按如下方式设置Varchar2长度的大小,但仍有相同的问题。
p.OracleDbType = OracleDbType.Varchar2;
p.Size = 4000;
也试过这个,没有运气:
string sql = "INSERT INTO STAGING(\"COLUMN1\") VALUES (CAST(:COLUMN1 AS VARCHAR2(4000))";
有什么想法吗?
这似乎是一个类似的问题:https://community.oracle.com/thread/3649551
更新 我怀疑可能存在某种字符集问题,这使得长度超出预期,因此为了排除这一点,我减少了我们尝试将数据插入到VARCHAR2中的表的列长度( 1000),假设这会使最大允许字符长度为250 - 但事实并非如此。抛出此异常之前工作的最大值仍为1000。
更新2 我找到了一个可以解决这个问题的oracle补丁。我会尝试获取此补丁并进行验证。 https://support.oracle.com/epmos/faces/PatchDetail?patchId=20361140&requestId=18735492
更新3 oracle补丁并没有为我解决这个问题。我试图遍历所有参数绑定状态,但它们都表示成功。
catch (Exception ex)
{
foreach (OracleParameter p in cmd.Parameters)
{
foreach (var s in p.ArrayBindStatus)
{
if (s != OracleParameterStatus.Success)
{
}
}
}
}
更新4 似乎这是Oracle Managed API中的一个错误,这是一个可以重现该问题的示例类。
namespace OracleBindError
{
using Oracle.ManagedDataAccess.Client;
using System.Data;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string testTable = "BIND_TEST_TABLE";
string connString = "[conn string here]";
string dropTable =
@"DECLARE pEXISTS NUMBER;
BEGIN
SELECT COUNT(*) INTO pEXISTS FROM USER_TABLES WHERE TABLE_NAME = '" + testTable + @"';
IF(pEXISTS > 0) THEN
EXECUTE IMMEDIATE 'DROP TABLE " + testTable + @"';
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE " + testTable + @" (COLUMN1 VARCHAR2(4000), COLUMN2 VARCHAR2(4000))';
END;";
string[] greaterThanOneThousand = new string[] {
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkldfdffd",
};
string insertStatement = "INSERT INTO " + testTable + "(\"COLUMN1\",\"COLUMN2\") VALUES (:COLUMN1,:COLUMN2)";
using (OracleConnection conn = new OracleConnection(connString))
{
conn.Open();
OracleCommand dropCmd = new OracleCommand(dropTable, conn);
dropCmd.ExecuteNonQuery();
using (OracleCommand cmd = conn.CreateCommand())
{
cmd.CommandText = insertStatement;
cmd.CommandType = CommandType.Text;
cmd.BindByName = true;
cmd.ArrayBindCount = greaterThanOneThousand.Length;
var p = new OracleParameter { ParameterName = "COLUMN1" };
p.OracleDbType = OracleDbType.Varchar2;
p.Value = greaterThanOneThousand.ToArray();
cmd.Parameters.Add(p);
var p2 = new OracleParameter { ParameterName = "COLUMN2" };
p2.OracleDbType = OracleDbType.Varchar2;
p2.Value = new string[] { null };
cmd.Parameters.Add(p2);
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
}
}
找到解决方法 如果我在我的参数中将OracleDbType从Varchar2更改为NVarchar2,则可以正常工作。
var p = new OracleParameter { ParameterName = "COLUMN1" };
p.OracleDbType = OracleDbType.NVarchar2;
p.Value = greaterThanOneThousand.ToArray();
cmd.Parameters.Add(p);
var p2 = new OracleParameter { ParameterName = "COLUMN2" };
p2.OracleDbType = OracleDbType.Varchar2;
p2.Value = new string[] { " " };
cmd.Parameters.Add(p2);
变通 解决方法是在.net端的参数中使用NVARCHAR2。
答案 0 :(得分:0)
您正在分配类型数组&#34; T&#34;变得有价值。然而,数据库期望它是VARCHAR2(4000),这相当于字符串。尝试将值转换为字符串。