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 클래스에서 급하게 따온거라 좀 변수나 이런게 조잡하기는 하지만
전체의 흐름을 한번만 보시면 다른 것에도 쉽게 적용하실수 있을거 같아서.....
그럼 즐프하시구여 ^^ 틀린게 있다면 이해해 주시길 바랍니다.
제가 설명드리려고 하는 것은 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 클래스에서 급하게 따온거라 좀 변수나 이런게 조잡하기는 하지만
전체의 흐름을 한번만 보시면 다른 것에도 쉽게 적용하실수 있을거 같아서.....
그럼 즐프하시구여 ^^ 틀린게 있다면 이해해 주시길 바랍니다.