Поддержка параметров OUT и INOUT для вызовов хранимых процедур в драйвере ODBC Informix

Новая функция для драйвера ODBC CSDK

Узнайте о том, как реализация поддержки параметров OUT и INOUT в драйвере ODBC IBM® Informix® ODBC повышает эффективность вызовов хранимых процедур в Informix. Узнайте, как применять различные типы параметров (такие как OUT и INOUT) для отправки или извлечения данных из базы данных Informix с использованием вызовов процедур. Несмотря на то, что типы OUT и INOUT являются стандартными типами параметров, до выпуска версии CSDK 3.50.xC4 они не поддерживались драйвером ODBC.

Коллол Кумар Мисра, старший инженер-программист, IBM

Photo of author Kollol MisraКоллол Кумар Мисра (Kollol Kumar Misra) работает в индийской лаборатории IBM в Бангалоре. Коллол имеет более чем семилетний опыт работы в области ИТ. В настоящее время Коллол занимает должность ведущего инженера по разработке набора инструментальных средств IBM Informix CSDK (Client Software Development Kit) в Индийской лаборатории программного обеспечения (India Software Lab).



Шешнарайян Агравал, специалист по архитектуре систем программного обеспечения, IBM

Shesh Agrawal photoШешнарайя Агравал (Sheshnaraya Agrawal) или просто Шеш (Shesh) работает в индийской лаборатории IBM в Бангалоре. Шеш имеет более чем 13-летний опыт работы в области ИТ. В настоящее время Шеш занимает должность ведущего инженера по разработке распределенного продукта IBM Optim в Индийской лаборатории программного обеспечения (India Software Lab). Шеш является обладателем награды IBM за полученные патенты, имеет степень магистра по специальности «Вычислительная техника». До начала участия в разработке продукта Optim Шеш в течение более чем 8 лет занимался разработкой набора инструментальных средств IBM Informix CSDK (Client Software Development Kit). Шеш выступал с разнообразными докладами по продуктам Optim и Informix на различных национальных и международных конференциях, таких как IOD Las Vegas, IIUG Lenexa и Software Universe.



06.12.2012

Введение

Хранимые в базах данных процедуры представляют собой наборы предварительно созданных на сервере и скомпилированных SQL-операторов, которые вызываются и выполняются приложениями баз данных. Могут иметь место процедуры с возвращаемым значением или без такового, а также с параметрами или без них. Существуют три варианта параметризованных хранимых процедур:

  1. Параметр OUT — с использованием этого параметра вы можете только получать значения из процедуры. Передавать значения в параметры OUT в вызовах хранимых процедур нельзя. После успешного выполнения хранимой процедуры все значения параметров OUT присваиваются соответствующим связанным переменным.
  2. Параметр IN — с использованием этого параметра вы можете только отправлять значения в хранимую процедуру. В теле хранимой процедуры можно выполнять запросы на основании входного значения. Это параметр по умолчанию, ключевое слово IN является опционным.
  3. Параметр INOUT — с использованием этого параметра вы можете только отправлять и получать значения из процедуры. Применение этого параметра обеспечивает преимущества параметров OUT и IN с использованием единственной связанной переменной. .

ПРИМЕЧАНИЕ: если тип параметра не определен явным образом, по умолчанию считается, что это параметр типа IN.

Начиная с версии CSDK 3.50xC4 в ODBC-драйвере Informix CSDK реализована поддержка параметров OUT и INOUT для хранимых процедур. Ранее ODBC-драйвер CSDK поддерживал только параметр IN, и пользователи получали сообщения об ошибке при попытке отправить параметры типов OUT или INOUT в хранимой процедуре. Из этой статьи вы узнаете о том, как реализовать новые поддерживаемые возможности в своих собственных хранимых процедурах Informix. Реализация проиллюстрирована примерами кода на C для ODBC CSDK.

В целом в приложениях ODBC существуют два типа SQL-запросов:

  • SQL-запросы, которые должны выполняться только один раз без необходимости передачи или привязки значений параметров во время выполнения.
  • SQL-запросы, которые должны выполняться несколько раз с разными наборами данных. Запросы такого типа подготавливаются только один раз (для оптимизации производительности) и выполняются несколько раз с разными наборами связанных данных.

Поскольку в этой статье речь идет о параметрах OUT и INOUT, использование подготовленных операторов является единственным методом, который вы можете применять для связывания переменных с параметрами OUT и INOUT процедуры. Приведенный ниже пример иллюстрирует выполнение SQL-запроса без его подготовки.

Листинг 1. Выполнение операторов
rc = SQLExecDirectW (hstmt, L"execute procedure testproc ()", SQL_NTS );

Подготовленный оператор компилируется и оптимизируется один раз и может использоваться многократно путем настройки разных значений параметров. Для многократного выполнения одного и того же оператора предпочтительнее использовать подготовленные операторы. Поскольку оператор хранится в скомпилированном виде, для его выполнения требуется меньше времени. Преимущество использования такого оператора заключается в том, что подготовленный оператор является не обычным, а предварительно скомпилированным SQL-оператором.

Листинг 2. Подготовка и выполнение операторов
rc = SQLExecDirectW (hstmt, L"execute procedure testproc(?)" , SQL_NTS ); 
rc = SQLBindParameter(hstmt,1, SQL_PARAM_INPUT, SQL_C_LONG,
                                           SQL_INTEGER,4,0,&param1_val,0,&output_len);
param1_val=100;
rc = SQLExecute(hstmt);
/*мы подготовили sql-оператор, эквивалентный "execute procedure testproc(100)".*/

Выполнение хранимых процедур

Существуют два метода, которые могут применяться приложением для выполнения хранимой процедуры с использованием драйвера ODBC Informix:

  • EXECUTE PROCEDURE <имя процедуры>
  • {call <имя процедуры> }

Первый синтаксис напрямую предоставляется базой данных Informix. Для получения дополнительной информации обратитесь к сведениям о синтаксисе хранимых процедур баз данных Informix, доступным в Информационном центре.

Второй синтаксис относится к стандартной управляющей последовательности ODBC. Преимущество заключается в том, что одно и то же приложение ODBC может использоваться для выполнения хранимой процедуры в отношении баз данных разных разработчиков. Это позволяет избежать использования специфических вызовов для баз данных каждого такого разработчика по отдельности.

Для получения представления о практическом использовании хранимых процедур создадим следующую хранимую процедуру в базе данных Informix.

Листинг 3. Создание тестовой хранимой процедуры
CREATE PROCEDURE testproc() returning int
RETURN 1234;
END PROCEDURE;

Приведенные ниже примеры иллюстрируют оба типа синтаксиса.

Листинг 4. Выполнение процедуры с использованием оператора execute procedure
rc = SQLExecDirectW (hstmt, L"execute procedure testproc ()", SQL_NTS );
Листинг 5. Выполнение процедуры с использованием оператора call
rc = SQLExecDirectW (hstmt, L"{call testproc()}" , SQL_NTS ); 
rc = SQLFetch (hstmt);
rc = SQLGetData(hstmt, 1, SQL_C_LONG,&ret_val,4,&buffLen);

В ret_val в качестве возвращаемого результата будет сохраняться 1234. В этом примере реализуется простое возвращение значения 1234. В используемых на практике сценариях может содержаться 1000 строк SQL-операторов, которые реализуют очень сложную логику и возвращают выходные данные пользователю.

ПРИМЕЧАНИЕ: драйвер ODBC Informix будет поддерживать параметры OUT и INOUT в синтаксисе {call <имя процедуры>}. Соответствующие примеры приводятся в следующем разделе.


Возврат значения из хранимой процедуры

Создайте следующую процедуру в базе данных Informix.

Листинг 6. Создание простой процедуры
CREATE PROCEDURE testproc() returning int
RETURN 100;
END PROCEDURE;

При выполнении хранимой процедуры существуют два способа получения возвращаемого значения:

  • The SQLGetData() API
  • The SQLBindParameter() API

Когда хранимая процедура возвращает какое-либо значение, пользователи могут получить это возвращаемое значение с помощью API SQLGetData(). Приведенный ниже пример иллюстрирует использование указанного интерфейса API для извлечения возвращаемого значения из хранимой процедуры.

Листинг 7. Получение возвращаемого значения с использованием вызова API SQLGetData()
rc = SQLExecDirectW (hstmt, L"{call testproc()}" , SQL_NTS ); 
rc = SQLFetch (hstmt);
rc = SQLGetData(hstmt, 1, SQL_C_LONG,&ret_val,4,&buffLen);

После успешного выполнения значение переменной ret_val будет равно 100.

При использовании второго метода вы можете извлекать возвращаемое значение путем присвоения ему переменной с использованием API SQLBindParameter(). При применении этого метода переменная присоединяется к возвращаемому значению хранимой процедуры. После успешного выполнения переменной ret_val будет присвоено значение 100. Очевидно, что этот метод предпочтительнее предыдущего вследствие меньших объемов кода и необходимой обработки. Приведенный ниже пример поясняет использование API SQLBindParameter() для извлечения возвращаемого значения из хранимой процедуры.

Листинг 8. Получение возвращаемого значения с использованием вызова API SQLBindParamater()
 rc = SQLPrepare(hstmt, L"{?=call testproc()}" , SQL_NTS );
 rc = SQLBindParameter(hstmt,1, SQL_PARAM_OUTPUT, SQL_C_LONG,
                            SQL_INTEGER,4,0,&ret_val,0,&output_len);
 rc = SQLExecute(hstmt);

ПРИМЕЧАНИЕ: когда хранимая процедура возвращает какое-либо значение и содержит параметры OUT и INOUT, для получения данных может использоваться только API SQLBindParameter().


Выполнение хранимой процедуры с параметром OUT

Создайте следующую процедуру в базе данных Informix.

Листинг 9. Создание образца процедуры
CREATE PROCEDURE testprocout ( OUT param1 int)
let param1=3210;
END PROCEDURE;

Ниже приведен пример использования параметра OUT в хранимой процедуре в приложении ODBC Informix. При работе в версии младше 3.50.xC4 сделать это не удалось бы. Этот пример демонстрирует, как можно получить данные, возвращаемые из хранимой процедуры в качестве параметра OUT. В первую очередь подготавливается запрос, за которым следует привязка переменной out_val, где будут сохраняться выходные данные параметра вывода хранимой процедуры param1. API SQLExecute() выполняет хранимую процедуру. После успешного выполнения переменная out_val принимает значение 3210.

Листинг 10. Выполнение хранимой процедуры с параметром OUT
  rc = SQLPrepare(hstmt,"{call testprocout(?)}", SQL_NTS);
  rc = SQLBindParameter(hstmt,1, SQL_PARAM_OUTPUT, SQL_C_LONG,
                          SQL_INTEGER,4,0,&out_val,0,&output_len);
  rc = SQLExecute(hstmt);

Выполнение хранимой процедуры с параметром INOUT

Создайте следующую процедуру в базе данных Informix.

Листинг 11. Создание хранимой процедуры
CREATE PROCEDURE testprocinout ( INOUT param1 int)
let param1=param1*2;
END PROCEDURE;

Как и в приведенном выше примере с параметром OUT, приложение может использовать тот же самый интерфейс API SQLBindParameter() для присоединения параметра INOUT. Разница заключается в третьем параметре, передаваемом как SQL_PARAM_INPUT_OUTPUT. Поскольку это параметр типа INOUT, он будет использоваться в качестве входных и выходных данных. Как показано в приведенном ниже примере, переменной inout_val присваивается значение 100, а после успешного выполнения API SQLExecute() это значение должно измениться на 200 (обратите внимание на тело хранимой процедуры, поскольку в нем производится умножение входного значения на 2).

Листинг 12. Выполнение хранимой процедуры с параметром INOUT
rc = SQLPrepare(hstmt,"{call testprocinout(?)}", SQL_NTS);
rc = SQLBindParameter(hstmt,1, SQL_PARAM_INPUT_OUTPUT, SQL_C_LONG,
                           SQL_INTEGER,4,0,&inout_val,0,&output_len);
inout_val=100;
rc = SQLExecute(hstmt);

Выполнение хранимой процедуры с параметром OUT для типов данных BLOB и CLOB

Создайте указанные ниже таблицу и хранимую процедуру в базе данных Informix для получения данных BLOB с использованием параметра OUT: create table tab_blob1(c_blob BLOB, c_int INTEGER, c_char VARCHAR(20));.

Вставьте одну запись (по выбору пользователя) в таблицу out_param_blob.

Создайте следующую процедуру в базе данных Informix с параметром OUT типа данных BLOB.

Листинг 13. Создание образца процедуры с параметром OUT типа данных BLOB
CREATE PROCEDURE out_param_blob(OUT blobparam BLOB, 
               OUT intparam int, OUT charparam VARCHAR(20))
select c_blob, c_int, c_char into blobparam, intparam, charparam from tab_blob1;
END PROCEDURE;

Выполните следующие операторы для подготовки запроса и связывания переменной с параметром.

Листинг 14. Выполнение процедуры с параметром OUT BLOB
cbParm1 = SQL_NULL_DATA;
rc = SQLPrepare(hstmt, (UCHAR *)"{call out_param_blob(?, ?, ?)}", SQL_NTS);
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
		sizeof(blob_buffer), 0, blob_buffer, sizeof(blob_buffer), &cbParm1);
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 
				3, 0, &sParm1, 0, &cbParm2);
rc = SQLBindParameter (hstmt, 3, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR,
			 sizeof(schar), 0, schar, sizeof(schar), &cbParm3);
rc = SQLExecute(hstmt);

После успешного выполнения процедуры blob_buffer будет содержать данные столбцов BLOB, извлеченные из хранимой процедуры. Чтобы извлечь данные BLOB в качестве параметра OUT, используйте SQL-тип ODBC как SQL_LONGVARBINARY и cbParm1 = SQL_NULL_DATA.

Создайте указанные ниже таблицу и хранимую процедуру в базе данных Informix для получения данных CLOB с использованием параметра OUT: create table tab_clob1(c_clob CLOB, c_int INTEGER, c_char VARCHAR(20));.

Вставьте одну запись (по выбору пользователя) в таблицу out_param_clob.

Создайте следующую процедуру в базе данных Informix с параметром OUT типа данных CLOB.

Листинг 15. Создание образца процедуры с параметром OUT типа данных CLOB
CREATE PROCEDURE out_param_clob(OUT clobparam CLOB, 
			OUT intparam int, OUT charparam VARCHAR(20))
select c_clob, c_int, c_char into clobparam, intparam, charparam from tab_clob1;
END PROCEDURE;

Выполните следующие операторы для подготовки запроса и связывания переменной с параметром.

Листинг 16. Выполнение хранимой процедуры с параметром OUT CLOB
cbParm1 = SQL_NULL_DATA;
rc = SQLPrepare(hstmt, (UCHAR *)"{call out_param_clob(?, ?, ?)}", SQL_NTS);
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY, SQL_LONGVARCHAR,
		sizeof(clob_buffer), 0, clob_buffer, sizeof(clob_buffer), &cbParm1);
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 
				3, 0, &sParm1, 0, &cbParm2);
rc = SQLBindParameter (hstmt, 3, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR,
			 sizeof(schar), 0, schar, sizeof(schar), &cbParm3);
rc = SQLExecute(hstmt);

После успешного выполнения процедуры clob_buffer будет содержать данные столбцов CLOB, извлеченные из хранимой процедуры. Чтобы извлечь данные CLOB в качестве параметра OUT, используйте SQL-тип ODBC как SQL_LONGVARCHAR и cbParm1 = SQL_NULL_DATA.


Демонстрационная программа

Приведенный ниже образец программы демонстрирует порядок использования параметров OUT и INOUT для типов данных (например, INTEGER и CHARACTER) с использованием вызовов API ODBC-драйвера Informix CSDK.

Эта программа удаляет хранимую процедуру proc1, если она существует в базе данных. Затем создается хранимая процедура proc1 с типами OUT и INOUT в сигнатуре. Как видите, связанной переменной для типа INOUT, которая предоставляет какое-либо значение (например, 3) в качестве входных данных, является idval в качестве SQL_PARAM_INPUT_OUTPUT. Поскольку используется параметр INOUT, конечный результат будет основываться на входном значении (3), а все операции производятся в хранимой процедуре (в данной демонстрационной программе производится умножение на 100). Программа выполняет хранимую процедуру, используя ODBC-драйвер CSDK. Во время выполнения программа отправляет данные в хранимую процедуру. После выполнения программа выводит выходные данные, полученные в результате вызова хранимой процедуры.

Листинг 17. Демонстрационное приложение с использованием параметров OUT и INOUT и возвращаемого значения
int main()
{
RETCODE retcode=SQL_SUCCESS;
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLHSTMT hstmt= SQL_NULL_HSTMT;
char connectOutput[1024];
SQLINTEGER Connectresult;
char *dsn="dsn=newdsn";
int idval = 0, len=0,ret_val=0;
char nameval[50];
SQLCHAR *delstmt = (SQLCHAR *)"drop procedure proc1";
SQLCHAR *createstmt = 
      (SQLCHAR *)"create procedure proc1(INOUT id int, OUT name varchar(50))"
"  returning int "
"let id=100*id; "
"let name='Shesh'; "
"RETURN id*2; "
"end procedure; ";
SQLCHAR *callstmt = (SQLCHAR *)"{?=call proc1(?,?)} ";

retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
retcode = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLDriverConnect(hdbc, NULL ,dsn,SQL_NTS, connectOutput, sizeof(connectOutput),
                  &Connectresult , SQL_DRIVER_NOPROMPT);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
retcode = SQLExecDirect(hstmt, delstmt, SQL_NTS);
retcode = SQLExecDirect(hstmt, createstmt, SQL_NTS);
retcode = SQLPrepare(hstmt, callstmt, SQL_NTS);
retcode = SQLBindParameter (hstmt,1, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0,
              (VOID *)&ret_val, 0,0);
retcode = SQLBindParameter (hstmt,2, SQL_PARAM_INPUT_OUTPUT, SQL_C_LONG, SQL_INTEGER,
                0, 0, (VOID *)&idval, 0,0);
idval=3;
retcode = SQLBindParameter (hstmt,3,SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 50, 0,
                (VOID *)&nameval, 50,&len);
retcode = SQLExecute(hstmt);
printf("Data id=%d , Name=%s , Return=%d\n", idval,nameval,ret_val);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return retcode;
}

Входные данные: Data id=300 , Name=Shesh , Return=600.

Приведенный ниже пример программы демонстрирует порядок использования параметров OUT и INOUT для различных типов данных (например, BIGINT, BLOB, CLOB и DATE) в вызове хранимой процедуры. Цель этой программы заключается в следующем:

  1. Удаление таблицы EmpDetail, если она существует
  2. Создание таблицы EmpDetail, в которой хранятся порядковый номер, фамилия, адрес и фотография сотрудника, а также дата приема сотрудника на работу.
  3. Вставка одной записи в эту таблицу.
  4. Выполнение хранимой процедуры, которая будет считывать сведения о сотруднике из таблицы базы данных EmpDetail и возвращать их с использованием параметра OUT.

Пользователю необходимо иметь два файла в заданном каталоге, содержащем соответствующие данные:

  • c:\address.txt — этот файл содержит информацию об адресе сотрудника.
  • c:\image.jpg — этот файл содержит фотографию сотрудника. По умолчанию размер фотографии не должен превышать 50000 байтов. Для добавления изображения большего размера сконфигурируйте #define IMAGESIZE 50000 в исходном коде для фактического размера в байтах. .

После вызова хранимой процедуры эта программа выводит идентификатор сотрудника, его фамилию, адрес, дату приема на работу и создает идентичное изображение в файле c:\out_image.jpg, чтобы пользователь мог сравнить данную фотографию с входной фотографией, находящейся в файле c:\image.jpg.

Листинг 18. Демонстрационное приложение с использованием параметров OUT и INOUT и с типами данных Bigint, BLOB, CLOB и Date
/*Подготовьте файлы c:\address.txt и c:\image.jpg для проверки работы 
с типами данных CLOB и BLOB
Установите значения IMAGESIZE и ADDRSIZE в соответствии с фактическим размером файлов*/

#define IMAGESIZE 50000
#define ADDRSIZE 1024
int main()
{
RETCODE retcode;
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLHSTMT hstmt= SQL_NULL_HSTMT;
char connectOutput[1024];
SQLINTEGER Connectresult;
char *dsn="dsn=newdsn";
SQLBIGINT id=0;
SQLCHAR name[100]={0,};
SQLDATE doj[20]={0,};
char image[IMAGESIZE], address[ADDRSIZE];
int length1=0,length2=SQL_NTS,length5=SQL_NTS;
int length3=SQL_NULL_DATA,length4=SQL_NULL_DATA;
FILE *fp;
SQLCHAR *drop_table = (SQLCHAR *)"drop table EmpDetail";
SQLCHAR *create_table = (SQLCHAR *)"create table EmpDetail"
"(empid bigint,empname varchar(100), empaddress CLOB, empimage BLOB,empdoj DATE)";
SQLCHAR *insert_table = (SQLCHAR *)"insert into EmpDetail values(4564789,"
"'Kollol Kumar Misra', filetoclob('c:\\address.txt','client'),"
"filetoblob('c:\\image.jpg','client'),'01-01-2001')";
SQLCHAR *delstmt = (SQLCHAR *)"drop procedure getempdetail";
SQLCHAR *createstmt = (SQLCHAR *)"create procedure getempdetail"
"(INOUT id BIGINT,OUT name VARCHAR(20), "
"OUT address CLOB, OUT image BLOB,OUT doj DATE)\n"
"select * into id,name,address,image,doj from EmpDetail;\n"
"end procedure;";
SQLCHAR *callstmt = (SQLCHAR *)"{call getempdetail(?,?,?,?,?)} ";
retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
retcode = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLDriverConnect(hdbc, NULL ,dsn,SQL_NTS, connectOutput,
          sizeof(connectOutput), &Connectresult , SQL_DRIVER_NOPROMPT);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
retcode = SQLExecDirect(hstmt, drop_table, SQL_NTS);
retcode = SQLExecDirect(hstmt, create_table, SQL_NTS);
retcode = SQLExecDirect(hstmt, insert_table, SQL_NTS);
retcode = SQLExecDirect(hstmt, delstmt, SQL_NTS);
retcode = SQLExecDirect(hstmt, createstmt, SQL_NTS);
retcode = SQLPrepare(hstmt, callstmt, SQL_NTS);
retcode = SQLBindParameter (hstmt,1,SQL_PARAM_INPUT_OUTPUT, SQL_C_SBIGINT,
          SQL_BIGINT, 0, 0, (VOID *)&id, 0,&length1);
retcode = SQLBindParameter (hstmt,2,SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_CHAR,
          sizeof(name), 0, (VOID *)name, sizeof(name),&length2);
retcode = SQLBindParameter (hstmt,3,SQL_PARAM_OUTPUT, SQL_C_BINARY,
                SQL_LONGVARCHAR, sizeof(address), 0, (VOID *)address, 
                sizeof(address),&length3);
retcode = SQLBindParameter (hstmt,4,SQL_PARAM_OUTPUT, SQL_C_BINARY,
          SQL_LONGVARBINARY, sizeof(image), 0, (VOID *)image, 
          sizeof(image),&length4);
retcode = SQLBindParameter (hstmt,5,SQL_PARAM_OUTPUT, SQL_C_CHAR,
          SQL_CHAR, sizeof(doj), 0, (VOID *)doj, sizeof(doj),&length5);
retcode = SQLExecute(hstmt);
printf("ID=%lld \nNAME=%s \nDOJ=%s \n",id,name,doj);
fp=fopen("c:\\out_image.jpg","w+b");
fwrite(image,1,length4,fp);
fclose(fp);
fp=fopen("c:\\out_address.txt","w+b");
fwrite(address,1,length3,fp);
fclose(fp);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return retcode;
}

Выходные данные:

ID=4564789
NAME=Kollol Kumar Misra
DOJ=2001-01-01

Сравните файлы out_image.jpg и out_address.txt с исходными файлами и убедитесь в том, что извлечение и вставка данных прошли корректно.


Заключение

В этой статье продемонстрированы возможности применения параметров OUT и INOUT с использованием драйвера ODBC Informix. До появления версии CSDK 3.50.xC4 ODBC-драйвер CSDK не поддерживал обработку типов параметров OUT и INOUT. Поэтому при попытке пользователей выполнить вызовы хранимых процедур с параметрами OUT и INOUT драйвер выдавал сообщение об ошибке. Как упоминалось выше, параметры типа OUT и INOUT являются стандартными и присутствуют в большинстве баз данных. Начиная с версии CSDK 3.50.xC4, ODBC-драйвер CSDK начал поддерживать типы параметров OUT и INOUT в вызовах процедур. Это помогает вам создавать и выполнять более сложный код хранимых процедур и вызывать хранимые процедуры внутри приложения с использованием ODBC-драйвера CSDK. Приведенные примеры кода на C демонстрируют порядок создания приложений с использованием ODBC-драйвера Informix. В нескольких местах приводятся примечания, указывающие на правильный порядок работы с вызовами хранимых процедур с параметрами OUT и INOUT.


Загрузка

ОписаниеИмяРазмер
Параметрыoutparam.zip227 КБ

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Information Management
ArticleID=850370
ArticleTitle=Поддержка параметров OUT и INOUT для вызовов хранимых процедур в драйвере ODBC Informix
publish-date=12062012