PL/SQL이 OracleCommand 객체의 CommandText이고 저장 프로 시저 또는 함수가 아닌 여러 레코드/값에 대해 RefValue 매개 변수로 Ref Cursor를 사용하려는 경우 이해가 필요합니다. 심지어 가능합니다.저장된 함수 또는 프로 시저를 사용하지 않고 C# ODP.NET의 Oracle Ref Cursor를 ReturnValue 매개 변수로 사용하는 방법?
그럴 수 없다면, 내가하려는 것은 WHERE 절과 일치하는 일치하는 레코드 수를 알 수없는 PL/SQL 문을 발행하는 방법을 찾아서 모든 레코드의 ID 저장 프로 시저 또는 함수를 사용하지 않고 데이터베이스에 대한 단일 라운드 트립을 사용하여 OracleDataReader에서 업데이트되었습니다.
저는 SQL 연결을 사용하여 데이터를 검색/수정하는 기존 C# .NET 4.0 코드베이스와 통신하기 위해 ODP.NET을 사용하여 Oracle 11g를 사용하고 있습니다. 내가 그렇게 같은 외모를 사용하고 단순화 된 테스트 테이블 정의 :
CREATE TABLE WorkerStatus
(
Id NUMERIC(38) NOT NULL
,StateId NUMERIC(38) NOT NULL
,StateReasonId NUMERIC(38) NOT NULL
,CONSTRAINT PK_WorkerStatus PRIMARY KEY (Id)
)
난과 같이 세 가지 테스트 값으로 테이블을 채울 사전 :
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (1, 0, 0)';
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (2, 0, 0)';
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (3, 0, 0)';
END;
기존의 SQL 문, 스크립트 파일에서로드 나는 오지고있어 어디 분리하려고 시도하는 작은 C# 테스트 프로그램을 만들었습니다
DECLARE
TYPE id_array IS TABLE OF WorkerStatus.Id%TYPE INDEX BY PLS_INTEGER;
t_ids id_array;
BEGIN
UPDATE WorkerStatus
SET
StateId = :StateId
,StateReasonId = :StateReasonId
WHERE
StateId = :CurrentStateId
RETURNING Id BULK COLLECT INTO t_Ids;
SELECT Id FROM t_Ids;
END;
:과 같이 Oracle_UpdateWorkerStatus2 이름과 OracleCommand.CommandText에 포함 보인다 그래서 순서를 변경, 내가 이름과 UpdatedRecords 매개 변수를 명명하지, 매개 변수 이름을 변경하려고했습니다
using System;
using System.Configuration;
using System.Data;
using System.Text;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
namespace OracleDbTest
{
class Program
{
static void Main(string[] args)
{
// Load the SQL command from the script file.
StringBuilder sql = new StringBuilder();
sql.Append(Properties.Resources.Oracle_UpdateWorkerStatus2);
// Build and excute the command.
OracleConnection cn = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleSystemConnection"].ConnectionString);
using (OracleCommand cmd = new OracleCommand(sql.ToString(), cn))
{
cmd.BindByName = true;
cn.Open();
OracleParameter UpdatedRecords = new OracleParameter();
UpdatedRecords.OracleDbType = OracleDbType.RefCursor;
UpdatedRecords.Direction = ParameterDirection.ReturnValue;
UpdatedRecords.ParameterName = "rcursor";
OracleParameter StateId = new OracleParameter();
StateId.OracleDbType = OracleDbType.Int32;
StateId.Value = 1;
StateId.ParameterName = "StateId";
OracleParameter StateReasonId = new OracleParameter();
StateReasonId.OracleDbType = OracleDbType.Int32;
StateReasonId.Value = 1;
StateReasonId.ParameterName = "StateReasonId";
OracleParameter CurrentStateId = new OracleParameter();
CurrentStateId.OracleDbType = OracleDbType.Int32;
CurrentStateId.Value = 0;
CurrentStateId.ParameterName = "CurrentStateId";
cmd.Parameters.Add(UpdatedRecords);
cmd.Parameters.Add(StateId);
cmd.Parameters.Add(StateReasonId);
cmd.Parameters.Add(CurrentStateId);
try
{
cmd.ExecuteNonQuery();
OracleDataReader dr = ((OracleRefCursor)UpdatedRecords.Value).GetDataReader();
while (dr.Read())
{
Console.WriteLine("{0} affected.", dr.GetValue(0));
}
dr.Close();
}
catch (OracleException e)
{
foreach (OracleError err in e.Errors)
{
Console.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
System.Diagnostics.Debug.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
}
}
cn.Close();
}
Console.WriteLine("Press Any Key To Exit.\n");
Console.ReadKey(false);
}
}
}
: 같은 보이는 본체를 가지고 RA-01036 "불법 변수 이름/번호"오류 UpdatedRecords는 처음 또는 마지막입니다. 지금까지 찾은 가장 가까운 것은 다음 StackOverflow 질문 (How to call an Oracle function with a Ref Cursor as Out-parameter from C#?)이지만 여전히 내가 말할 수있는 한 저장 함수를 사용합니다. SQL Developer에서 Oracle_UpdateWorkerStatus2 PL/SQL 스크립트를 실행
는, 내가 위의 코드와 같이 CurentStateId, StateId 및 StateReasonId에 대한 값을 입력 "귀속 입력"대화 상자가 열립니다 있지만, 다음과 같은 오류 보고서를 제공합니다
Error report:
ORA-06550: line 13, column 17:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 13, column 2:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
WorkerStatus 테이블을 정의하고 id_array 유형의 t_Ids 변수를 테이블로 선언했을 때 실제로 테이블이 존재하지 않는다고 말하는 이유를 알 수 없습니다. 여기에 도움을 주시면 대단히 감사하겠습니다.
권한/가시성 문제 일 수 있습니까? 스크립트 "Oracle_UpdateWorkerStatus2"를 실행중인 oracle 계정에 수동으로 연결할 때 workerstatus 테이블에서 선택할 수 있습니까? –
WorkerStatus 테이블에서 선택 및 삭제할 수 있습니다. 필자는 오라클에게 상당히 익숙하므로 ref 커서를 사용할 수 있어야하는 특별한 권한이 있는지는 모르지만 IT/DBA 기술자는 개발자가 일반적으로 사용하는 모든 권한을 설정해 주지만, 그래서 나는 이것이 특권의 문제라고 생각하지 않는다. 나는 그에게 월요일에 물을 것이다. – Paul
우리 DBA에 확인해 봤는데, 그는 내가하고있는 일을하기 위해 요구되는 특별한 특권을 알지 못합니다. 또한, 그는 내가 여기에있는 것을 빠르게 검사했고 그것이 작동하지 않는 이유를 보지 못했습니다. 내가 잘못하고있는 일에 대한 생각이나 목표를 달성하기위한 또 다른 방법? – Paul