Technical Article/펌

OLEDB에서 Stored Procedure 사용하기!

fiadot_old 2004. 2. 10. 16:27
안녕하세요 ^^;
제가 설명드리려고 하는 것은 CDynamicParameterAccessor를 이용한 방법입니다.
아래의 코드를 보시면 쉽게 이해가 가실겁니다.

// 이 부분은 접속하는 부분입니다. 어느 엑세서를 사용하시던지 공통입니다.
CDataSource    m_Connection;
CSession    m_Session;
HRESULT        hRet = E_FAIL;

USES_CONVERSION;
// pInitString에 들어가야 할 건 잘 아시리라 생각하구여 ^^
hRet = m_Connection.OpenFromInitializationString(T2COLE(pInitString));
if(FAILED(hRet))
{
     return FALSE;
}

hRet = m_Session.Open(m_Connection);
if(hRet != S_OK)
{
     return FALSE;
}

스토어프로시져의 구조에 따라 약 3가지 정도로 구분된다고 할 수 있습니다.
1. 반환값이 없고 출력 파라미터가 있는 경우.
    CREATE PROCEDURE sp_MyTest1
    @ret int OUTPUT
    AS
       set @ret = 1
   GO

2. 반환값이 없고 입력 출력 파라미터가 있는 경우.
    CREATE PROCEDURE sp_MyTest2
    @index int,
    @ret int OUTPUT
    AS
       set @ret = 1
   GO


3. 반환값이 있고 입력 출력 파라미터가 있는 경우.
    CREATE PROCEDURE sp_MyTest3
    @index int,
    @ret int OUTPUT
    AS
       -- 입력값은 받았지만 사용안하는걸로 이해해 주시길 ^^
       declare @aaa int
       set @aaa = 99
       select @aaa AS RESULT

       set @ret = 1
   GO


이 이외의 경우는 CDynamincAccessor를 사용하셔야 하겠죠 ^^

// 길게 쓰는게 귀찬으니깐 짧게 줄입니다. ^^
typedef CCommand<CDynamicParameterAccessor, CRowset, CMultipleResults>    CxParamCmd;

CxParamCmd   m_Cmd;

void* pDummy;
TCHAR pstrQuery[256];

// 쿼리가 입력되는 부분입니다. 즉 프로시져가 들어가는 부분이져.
// 다음과 같이 세 종류의 쿼리가 입력될 수 있습니다.
sprintf(pstrQuery, "sp_MyTest1 ? OUT " );
sprintf(pstrQuery, "sp_MyTest2 ?, ? OUT " );
sprintf(pstrQuery, "sp_MyTest3 ?, ? OUT " );

//  이 다음부터는 공통으로 사용되는 코드입니다.
hRet = m_Cmd.Create(m_Session, pstrQuery);
if(FAILED(hRet))
{
    AtlTraceErrorRecords(hRet);
    return FALSE;
}

hRet = m_Cmd.Prepare();
if(FAILED(hRet))
{
    AtlTraceErrorRecords(hRet);
    return FALSE;
}

hRet = m_Cmd.BindParameters(&m_Cmd.m_hParameterAccessor, m_Cmd.m_spCommand, &pDummy);
if(FAILED(hRet))
{
    AtlTraceErrorRecords(hRet);
    return FALSE;
}

// 입력 파라미터를 설정하는 부분입니다.
// 첫번째 파라미터의 값이 2라는 말입니다. ^^ 첫번째 프로시져를 사용하실 경우는 필요가 없겠죠 ㅍ.ㅍ
LONG nParamValue = 2;
m_Cmd.SetParam(1, &nParamValue);

// 쿼리를 실행합니다. Bind를 하지 않는다고 설정하시는게 나중을 위해 편하답니다 ^^
hRet = m_Cmd.Open(NULL,NULL,false);
if(FAILED(hRet))
{
    AtlTraceErrorRecords(hRet);
    return FALSE;
}

/*================================================================
    출력 파라미터만 받을 경우
================================================================*/
LONG ltemp = 0;
//  아래의 GetNextResult()는 여기서는 반드시 하시지 않아도 상관없습니다.
// 하셔두 되구여... 하지만 클래스화 하시면 하는게 편할지두 ^^
m_Cmd.GetNextResult(<emp);
LONG aa = *(LONG*)(m_Command.GetParam(2));

aa에 출력파라미터의 값이 들어있게 됩니다.

/*================================================================
    반환값과 출력 파라미터를 받을 경우
================================================================*/
// 반환값이 있는 경우라면 Bind를 합니다.
m_Cmd.Bind();

// 반환된 레코드 셑을 읽어옵니다.
// 각 필드값도 루프를 돌면서 값을 다 읽어 옵니다.
// 만약 레코드셑이 반환됐다면 루프를 돌면서 전체를 다 읽어야 하겠죠 ^^
// 그런건 아시리라 믿구여 ㅎ.ㅎ
// 여기서는 그냥 한개의 필드값만 읽어오는 걸루 ㅋㅋ
LONG dd = *(LONG*)(m_Cmd.GetValue(1));

// 모든 값을 다 읽으셨으면 출력파라미터를 읽을 준비를 합니다.
LONG ltemp = 0;
m_Cmd.GetNextResult(<emp);
LONG aa = *(LONG*)(m_Command.GetParam(2));

결론적으로 dd에는 반환값이, aa에는 출력파라미터값을 읽어오게 됩니다.

전체적인 코드를 보시면 쉽게 아시리라 믿습니다. 너무 설명을 난잡하게 해서 죄송하구요 ^^
제가 짠 OleDB 클래스에서 급하게 따온거라 좀 변수나 이런게 조잡하기는 하지만
전체의 흐름을 한번만 보시면 다른 것에도 쉽게 적용하실수 있을거 같아서.....

그럼 즐프하시구여 ^^ 틀린게 있다면 이해해 주시길 바랍니다.