empty_blob() //pass blob to oracle stored procedure 
//build by masterz 20050227 with VC2003, Windows 2003, Oracle 10g.
//The tip: user oledb provider string!
#include "stdafx.h"
#import "C:\PROGRA~1\COMMON~1\System\ado\msado15.dll" rename( "EOF", "adoEOF" )
struct InitOle
{
InitOle() { ::CoInitialize(NULL); }
~InitOle() { ::CoUninitialize(); }
} _init_InitOle_;
void PrintProviderError(ADODB::_ConnectionPtr pConnection);void print_properties(LPCTSTR name, ADODB::PropertiesPtr Properties)
{
long prop_count = Properties->GetCount();
printf("%s property count = %d\n",name,prop_count);
for(long i=0;i<prop_count;i++)
{
printf("%s property [%d]:%s\n",name,i,(LPCSTR)Properties->GetItem(i)->Name);
}
}
int main(int argc, char* argv[])
{
ADODB::_ConnectionPtr Conn1;
ADODB::_CommandPtr Cmd1;
ADODB::_ParameterPtr oldParam= NULL;
ADODB::_ParameterPtr inParam=NULL;
ADODB::_ParameterPtr blobParam=NULL;
_variant_t vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);
_variant_t vtEmpty2 (DISP_E_PARAMNOTFOUND, VT_ERROR);
_bstr_t bstrConnect="Provider=OraOLEDB.Oracle;Data Source=orcl;User Id=system;Password=oracle;";
_bstr_t bstrCreate ( "CREATE OR REPLACE PROCEDURE TEST_BLOB ( "
"p_USERNAME in CHAR,p_OLD in CHAR,p_PHOTO in BLOB default empty_blob() ) "
"as "
"begin "
"begin "
"insert into USERPHOTO( "
"USERNAME,OLD,PHOTO) "
"values (p_USERNAME,p_OLD,p_PHOTO); "
"commit; "
"end; "
"end TEST_BLOB;" );
_bstr_t bstrSP("{CALL TEST_BLOB(?,?,?)}" );
try
{
_variant_t varOptional(DISP_E_PARAMNOTFOUND,VT_ERROR); 
ADODB::_StreamPtr adostream;
adostream.CreateInstance(_T("ADODB.Stream"));
adostream->Type = ADODB::adTypeBinary;
adostream->Open(varOptional,ADODB::adModeUnknown, ADODB::adOpenStreamUnspecified, _T(""), _T("")); 
adostream->LoadFromFile("C:\\123.jpg");
_variant_t vReadTo = adostream->Read(ADODB::adReadAll); 
long blob_size = adostream->GetSize();
adostream->Close();_bstr_t bstrEmpty;
Conn1.CreateInstance( __uuidof( ADODB::Connection ) );
Cmd1.CreateInstance( __uuidof( ADODB::Command ) );
Conn1->ConnectionString = bstrConnect;
Conn1->Open( bstrConnect, bstrEmpty, bstrEmpty, -1 );
Conn1->Execute(bstrCreate,NULL,ADODB::adCmdText);
Cmd1->ActiveConnection = Conn1;
Cmd1->CommandText = bstrSP;
Cmd1->CommandType = ADODB::adCmdText;
Conn1->Properties->Refresh();
inParam = Cmd1->CreateParameter(_bstr_t("p_USERNAME"),ADODB::adChar,ADODB::adParamInput,2,_variant_t( "a" ));
Cmd1->Parameters->Append(inParam);oldParam = Cmd1->CreateParameter(_bstr_t("p_OLD"),ADODB::adChar,ADODB::adParamInput,4,_variant_t( "yes" ));
Cmd1->Parameters->Append(oldParam);blobParam = Cmd1->CreateParameter(_bstr_t("p_PHOTO"),ADODB::adLongVarBinary,ADODB::adParamInput,blob_size,vReadTo);
Cmd1->Parameters->Append(blobParam);
Cmd1->Properties->Refresh();
print_properties("Cmd1",Cmd1->Properties);ADODB::PropertyPtr prop = Cmd1->Properties->GetItem("SPPrmsLOB");
prop->PutValue(_variant_t(VARIANT_TRUE,VT_BOOL)) ;
Cmd1->Execute(NULL,NULL,ADODB::adExecuteNoRecords);
prop = Cmd1->Properties->GetItem("SPPrmsLOB");
prop->PutValue(_variant_t(VARIANT_FALSE,VT_BOOL)) ;
Conn1->Close();
}
catch(_com_error &e)
{
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\nCOM error occurred, Source : %s \n Description : %s \n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
PrintProviderError(Conn1);
}
printf("\nprogram end\n");
return 0;
}
VOID PrintProviderError(ADODB::_ConnectionPtr pConnection)
{
ADODB::ErrorPtr pErr = NULL;
long nCount = 0;
long i = 0;
if( (pConnection->Errors->Count) > 0)
{
nCount = pConnection->Errors->Count;
for(i = 0; i < nCount; i++)
{
pErr = pConnection->Errors->GetItem(i);
printf("\n\t Error number: %x\t%s", pErr->Number, (LPCSTR)pErr->Description);
}
}
}
上面这个,是可以运行的.
但我现在多了一个字段,CREATE OR REPLACE PROCEDURE TEST_BLOB ( "
"p_USERNAME in CHAR,p_OLD in CHAR,p_PHOTO in BLOB default empty_blob(), p_PHOTO1 in BLOB default empty_blob())然后我想通过存储过程来插入,第一个 blob是有数据的,但第二个为空,怎么操作? 存储过程已经定死,不能动.blobParam = Cmd1->CreateParameter(_bstr_t("p_PHOTO1"),ADODB::adLongVarBinary,ADODB::adParamInput,blob_size,vReadTo);
Cmd1->Parameters->Append(blobParam);
Cmd1->Properties->Refresh();
print_properties("Cmd1",Cmd1->Properties);
应该是这里修改一下,但我把 blob_size 改为0,调用不成功,请大家帮帮忙啊!

解决方案 »

  1.   

    对于地而个参数,由于他有Default,所以当你不想给他传值的时候。
    可以不理会这个参数。也就是说不用再你的cmd1里面append最后一个参数。
      

  2.   

    现在的问题是,不加就不行。 调用的存储过程看不到,现在多次测试的情况是很有可能没有default,也就是说,必须要append一个,急死啦!
      

  3.   

    试试这个:
    blobParam = Cmd1->CreateParameter(_bstr_t("p_PHOTO1"),ADODB::adLongVarBinary,ADODB::adParamInput,blob_size,VT_NULL); 
    Cmd1->Parameters->Append(blobParam); 
    Cmd1->Properties->Refresh(); 
    print_properties("Cmd1",Cmd1->Properties); 
      

  4.   

    append的方法
    直接把读的文件改成一个存在的长度为0k的文件,如 123.jpg为ok
    adostream->LoadFromFile("C:\\123.jpg"); 
    _variant_t vReadTo = adostream->Read(ADODB::adReadAll);  
    long blob_size = adostream->GetSize(); 
    ,这样 vReadTo 就为 VT_NULL, blob_size 为0; 此时是不能append的.
    提示如下:
       不正常地定义参数对象。提供了不一致或不完整的信息。" (1)}
    好像看过一个文章,此时要把blob_size 设为1, 然后可以append了.然后运行到下面
    ADODB::PropertyPtr prop = Cmd1->Properties->GetItem("SPPrmsLOB"); 
    prop->PutValue(_variant_t(VARIANT_TRUE,VT_BOOL)) ; 
    Cmd1->Execute(NULL,NULL,ADODB::adExecuteNoRecords); 

       {"ORA-24801: 在 OCI lob 函数中非法的参数值" (1)}
    再如果改为下面这样
    ADODB::PropertyPtr prop = Cmd1->Properties->GetItem("SPPrmsLOB"); 
    prop->PutValue(_variant_t(VARIANT_FALSE,VT_BOOL)) ; 
    Cmd1->Execute(NULL,NULL,ADODB::adExecuteNoRecords); 
    {"ORA-06550: 第 1 行, 第 7 列: 
    PLS-00306: 调用 'TEST_BLOB' 时参数数量或类型错误
    ORA-06550: 第 1 行, 第 7 列: 
    PL/SQL: Statement ignored" (1)}
    ADODB::PropertyPtr prop = Cmd1->Properties->GetItem("SPPrmsLOB"); 
    prop->PutValue(_variant_t(VARIANT_FALSE,VT_BOOL)) ;
    到底是为true还是false,因为如果有2个blob,一个为空,一个不为空!谢谢啊,麻烦您了!