Reputation: 1004
I can't figure out the problem on my code :
/* Declare a cursor for the FETCH statement. */
EXEC SQL DECLARE customer_cursor CURSOR FOR
SELECT CUSTOMER_ID, CUSTOMER_NAME
FROM CUSTOMER_TABLE
WHERE CUSTOMER_CARD_NUM = :argv[1];
if ( sqlca.sqlcode != 0 )
{
printf("Declare cursor failed\n");
return( sqlca.sqlcode );
}
EXEC SQL OPEN customer_cursor;
if ( sqlca.sqlcode != 0 )
{
printf("Open cursor failed\n");
return( sqlca.sqlcode );
}
EXEC SQL WHENEVER NOT FOUND GOTO no_match;
for ( ;; )
{
/* Fetching data */
EXEC SQL FETCH customer_cursor
INTO :var_customer_id, :var_customer_name;
if ( sqlca.sqlcode != 0 )
{
EXEC SQL CLOSE cust_data_cursor;
return ( sqlca.sqlcode );
}
/* Doing some stuff here */
processing_customer();
}
EXEC SQL CLOSE customer_cursor;
/* Handling the no data found here */
no_match:
printf("NO CUSTOMER MATCHING THIS CARD_NUM\n");
/* Some stuff */
......
return 1;
My query is supposed to return just one row or nothing, when nothing is returned all is ok, but when ther's a matching, the function processing_customer is executed and the strange is that the no_match is executed too.
Thanks for helping me to fix that.
Upvotes: 0
Views: 5581
Reputation: 863
Change your label "no_match" to "no_more_records" and you'll realize why it runs 2 times:
a) when there are no records, the FETCH raises the NOT FOUND condition inmediatly and therefore will go to the label "no_more_records"
b) when there is one (or more) record(s), the FETCH is executed returning the first record.
Then the
if ( sqlca.sqlcode != 0 )
evaluates to false (in fact, only useful to trap other problems) and then
processing_customer();
After it, the FETCH run again (by the infinity for) and behave as in (a): no_more_records condition arrives.
Upvotes: 0
Reputation: 191435
As @Roger Cornejo suggests, you need a way to not execute the 'no match' section if there is a match. no_match:
is just a label so there's nothing to tell your code not to execute that section. You either need to return before that label, or goto
something after it. You also need to close the cursor in the no-match scenario.
But this seems unnecessarily messy and as @Arion hinted you don't need an explicit cursor for this - just do a select into
and catch the exception.
EXEC SQL SELECT CUSTOMER_ID, CUSTOMER_NAME
INTO :var_customer_id, :var_customer_name
FROM CUSTOMER_TABLE
WHERE CUSTOMER_CARD_NUM = :argv[1];
if (sqlca.sqlcode == 1403)
{
printf("NO CUSTOMER MATCHING THIS CARD_NUM\n");
/* Some stuff */
......
return 1;
}
if (sqlca.sqlcode != 0)
{
return ( sqlca.sqlcode );
}
/* Doing some stuff here */
processing_customer();
You've said there will be zero or one rows; if there are more than one you'll get a too-many-rows error (ORA-02112).
Upvotes: 1