我正在开发一个C#应用程序,并将SQL语句从SQL Server转换为Oracle。我有一个块,其中值被插入主表和相关表中的几个记录。我需要确定主表中是否存在重复记录,如果是,则返回标记值到C#页面,否则插入记录,获取主表的PK并将其用于相关表的插入。到目前为止,我发现在块内部从Oracle返回值的最佳方法是使用InputOutput参数。 (如果语句中的任何地方都有一个BEGIN / END块,它将不允许我在没有INTO的情况下进行SELECT。)
在SQL Server中,尝试从不返回记录的SELECT语句加载变量只会导致变量保持不变。在Oracle中我发现我需要设置NO_DATA_FOUND异常来处理这个问题。我想要异常来设置返回标志;但我收到" ORA-06502:PL / SQL:数字或值错误"。
BEGIN
SELECT ID INTO :REPORTID FROM Report WHERE ExtractDt=:EXTRACTDT
AND REGION=:RGN;
EXCEPTION WHEN NO_DATA_FOUND THEN
SELECT -1 INTO :REPORTID FROM DUAL;
END;
这是我最接近的。 SELECT -1 ...行
发生错误REPORTID作为NUMBER类型的参数和方向InputOutput传入; EXTRACTDT是一个有效值的日期,RGN是一个varchar(2)字符串;两个输入参数。
编辑:如何从C#发送块到Oracle的示例:
OracleCommand psCmd = new OracleCommand();
psCmd.Connection = Conn; //Previously defined, valid & opened
psCmd.CommandType = CommandType.Text;
psCmd.CommandText = "{SQL STRING CONTAINING BLOCK, AS ABOVE}";
psCmd.Parameters.Add(new OracleParameter("REPORTID", OracleType.Number, 10) { Direction = ParameterDirection.InputOutput, Value = DBNull.Value });
psCmd.Parameters.Add(new OracleParameter("EXTRACTDT", OracleType.DateTime) { Value = dtExtract }); //C# DateTime with valid date
psCmd.Parameters.Add(new OracleParameter("RGN", OracleType.VarChar, 2) { Value = sRegion }); //C# String, 2 characters
psCmd.ExecuteNonQuery();
Int32 iID = (Int32)psCmd.Parameters["REPORTID"].Value;
//Cleanup, etc.
答案 0 :(得分:0)
问题可能是您使用的是OracleDbType而不是DbType。我通常使用OracleDbType,但在这种情况下,你要在某个变量中选择一个数字(选择-1进入...)并返回一个Decimal类型而不是Int。以下简单示例适用于我:
string connStr = "User Id=myuser;Password=mypass;Data Source=myinstance;";
using (OracleConnection con = new OracleConnection(connStr))
{
string s = @"BEGIN
select 1 into :TESTID from dual where 1=0;
EXCEPTION
when no_data_found then
select -1 into :TESTID from dual;
END;";
using (OracleCommand cmd = new OracleCommand(s, con))
{
con.Open();
Console.WriteLine("Running statement");
OracleParameter prm = new OracleParameter();
cmd.Parameters.Clear();
cmd.BindByName = true;
//prm = new OracleParameter("TESTID", OracleDbType.Int32, ParameterDirection.InputOutput); prm.Value = 0; cmd.Parameters.Add(prm);
prm = new OracleParameter();
prm.ParameterName = "TESTID";
prm.DbType = DbType.Int32; // don't use OracleDbType, will return decimal in some cases, not int
prm.Direction = ParameterDirection.InputOutput;
prm.Value = 0;
cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
// may have cast/conversion issues here if using OracleDbType
int id = Convert.ToInt32(cmd.Parameters["TESTID"].Value);
Console.WriteLine("ID is: " + id);
con.Close();
}
}