C# ODP.Net托管API-带字符串的数组绑定>;1000个字符
当使用ODP.Net托管API时,当使用数组绑定将数据插入VARCHAR2(4000)类型的列中,并且数组中行值的字符串长度大于1000个字符时,将引发以下异常: ORA-01461:只能为插入到长列中绑定长值 我尝试使用此选项,但仍然遇到相同的问题:C# ODP.Net托管API-带字符串的数组绑定>;1000个字符,c#,oracle,oracle11g,odp.net,odp.net-managed,C#,Oracle,Oracle11g,Odp.net,Odp.net Managed,当使用ODP.Net托管API时,当使用数组绑定将数据插入VARCHAR2(4000)类型的列中,并且数组中行值的字符串长度大于1000个字符时,将引发以下异常: ORA-01461:只能为插入到长列中绑定长值 我尝试使用此选项,但仍然遇到相同的问题: p.OracleDbType = OracleDbType.Clob; 还尝试如下设置Varchar2长度的大小,但仍然存在相同的问题 p.OracleDbType = OracleDbType.Varchar2; p.Size = 4000;
p.OracleDbType = OracleDbType.Clob;
还尝试如下设置Varchar2长度的大小,但仍然存在相同的问题
p.OracleDbType = OracleDbType.Varchar2;
p.Size = 4000;
我也试过这个,但运气不好:
string sql = "INSERT INTO STAGING(\"COLUMN1\") VALUES (CAST(:COLUMN1 AS VARCHAR2(4000))";
有什么想法吗
这似乎是一个类似的问题:
更新
我怀疑可能存在某种字符集问题,这使得长度比预期的长,所以为了排除这种情况,我将我们试图插入数据的表的列长度减少到VARCHAR2(1000),假设这将使允许的最大字符长度为250-但情况并非如此。引发此异常之前工作的最大值仍然是1000
更新2
我发现了一个oracle修补程序,可以解决此问题。我将尝试获取此修补程序并进行验证
更新3
oracle补丁没有为我解决这个问题。我试图遍历所有参数绑定状态,但它们都表示成功
catch (Exception ex)
{
foreach (OracleParameter p in cmd.Parameters)
{
foreach (var s in p.ArrayBindStatus)
{
if (s != OracleParameterStatus.Success)
{
}
}
}
}
更新4
这似乎是Oracle托管API中的一个bug,下面是一个可以重现该问题的示例类
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。您正在将类型为“T”的数组赋值。然而,数据库希望它是VARCHAR2(4000),这相当于string。尝试将值转换为字符串 我假设基表不使用长数据类型,并且您的数组类型是字符串?基表列的类型是VARCHAR2(4000)。在本例中,T的类型是字符串。字符串数组中参数中的值。
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();
}
}
}
}
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);