カーソル
1) Cygwinを起動します。

2) ソースを格納するディレクトリに移動
cd src でソースを格納するディレクトリに移動します。

3) ソース作成
カレントでviエディタを起動して test_cur.pgc を作成します。(Windowsのメモ帳などで作成してこのフォルダに保存してもよいです)内容は下です。
#include        <stdio.h>
#include        <string.h>
#include        <item_len.h>
EXEC SQL INCLUDE        table_neko;


int main(void)
{
        EXEC SQL BEGIN DECLARE SECTION;
        const char      * target = "mydb";
        const char      * user = "Owner";
        int             h_max_age;
        EXEC SQL END DECLARE SECTION;


        h_max_age = 4;

        EXEC SQL DECLARE cur_neko CURSOR FOR
                SELECT   COALESCE(name, 'unknown')
                        ,COALESCE(sex, 'unknown')
                        ,COALESCE(age, 0)
                        ,COALESCE(tail, 'unknown')
                FROM neko
                WHERE age <= :h_max_age
                ORDER BY age, sex;

        EXEC SQL CONNECT TO :target USER :user;

        if(sqlca.sqlcode != 0) {
                printf("error code = [%ld]\n", sqlca.sqlcode);
                return 1;
        }

        EXEC SQL OPEN cur_neko;

        if(sqlca.sqlcode != 0) {
                printf("error code = [%ld]\n", sqlca.sqlcode);
                return 1;
        }

        while(1) {

                memset(h_name, '\0', sizeof(h_name));
                memset(h_sex, '\0', sizeof(h_sex));
                memset(h_tail, '\0', sizeof(h_tail));

                EXEC SQL FETCH cur_neko INTO :h_name, :h_sex, :h_age, :h_tail;

                if(sqlca.sqlcode == 0) {
                        printf("%s %s %d %s\n", h_name, h_sex, h_age, h_tail);
                        continue;
                } else if(sqlca.sqlcode == ECPG_TOO_MANY_MATCHES) {
                        printf("ECPG_TOO_MANY_MATCHES error code = [%ld]\n", sqlca.sqlcode);
                        return 0;
                } else if(sqlca.sqlcode == ECPG_NOT_FOUND) {
                        printf("ECPG_NOT_FOUND error code = [%ld]\n", sqlca.sqlcode);
                        EXEC SQL CLOSE cur_neko;
                        break;
                } else if(sqlca.sqlcode == ECPG_MISSING_INDICATOR) {
                        printf("ECPG_MISSING_INDICATOR error code = [%ld]\n", sqlca.sqlcode);
                        return 1;
                } else {
                        printf("error code = [%ld]\n", sqlca.sqlcode);
                        return 1;
                }
        }

        return 0;
}

また、incの下に下の内容でitem_len.hを作成します。
#define		NAME_LEN		16
#define		SEX_LEN			1
#define		TAIL_LEN		16

さらに、incの下に下の内容でtable_neko.hを作成します。
EXEC SQL BEGIN DECLARE SECTION;
	char		h_name[NAME_LEN + 1];
	char		h_sex[SEX_LEN + 1];
	int		h_age;
	char		h_tail[TAIL_LEN + 1];
EXEC SQL END DECLARE SECTION;

4) ソースの説明
上のソースはカーソルを使うサンプルです。また、定数、ホスト変数が定義されたインクルードファイルを使うようにもしました。上のプログラムを実行するとnekoというテーブルから複数行を選択して表示します。
tem_len.hではテーブルnekoの文字型の項目の長さを定義してあります。table_neko.hではホスト変数を定義してあります。char型の配列のサイズはテーブルの項目のサイズよりも1バイト長く定義してあります。これによって各文字項目を文字列として扱うことが簡単に出来ます。

h_max_age = 4
上はカーソルを定義するときの条件に使うホスト変数に4を代入しています。これでageが4以下のレコードが選択されます。

EXEC SQL DECLARE cur_neko CURSOR FOR
ORDER BY age, sex;
上の2行の間のコードはカーソルを定義します。

EXEC SQL OPEN cur_neko;
上は、カーソルを開きます。開くとは、SQLを実行することです。プログラムからDBへSQLが発行されます。カーソルには問い合わせの結果の複数の行が格納されています

while(1)
無限ループを作成します。

memset(h_name, '\0', sizeof(h_name));
は文字列変数を0で初期化します。

EXEC SQL FETCH cur_neko INTO :h_name, :h_sex, :h_age, :h_tail;
は、カーソルから1行フェッチします。問い合わせの結果が(メモリ上?)に並んでいますがその上から順に1行づつ取得してホスト変数に値を代入します。

if(sqlca.sqlcode == ECPG_NOT_FOUND)
カーソルからレコードをフェッチして最後のレコードまでフェッチしてしまうとNOT_FOUNDが返されます。これを無限ループを抜ける条件としています。

EXEC SQL CLOSE cur_neko;
は、開いたカーソルを閉じます。カーソルは必ず閉じます。(開いているかを確認してから閉じる方がより良いコーディングですが。)


5) 実行
SELECT INTO 文の説明と同じ方法でプレコンパイル、コンパイルして実行します。
6節 埋め込みSQL   6節 埋め込みSQL