请注意看以下代码中的两条横线中的代码:
以下的代码是根据if中的条件执行不同的查询。相信很多场合都需要根据不同的条件执行不同的SQL,这是一个普遍的需求。
然而,编译并执行这段代码,发现n的值始终是1,哪怕在if的条件中写上false(应该执行else部分),执行的结果还是1(如果执行到else部分,结果应该是2)。难道是没有执行到else部分?在if 和else部分分别加上不同的打印,发现程序的流程确实执行了else部分,但是始终只使用if中定义的SQL。
不知道这算不算PRO*C的一个BUG。打开proc.exe编译后的代码查看,发现sqlstm.stmt = "SELECT..."; 这样的代码只有一句。看来proc.exe预编译器在编译PC文件的时候,始终以第一个声明游标的SQL为准。
以上的代码说明:PRO*C中想要根据不同的条件执行不同的SQL,不能采用这样的写法。
如何解决呢?变换一下写法即可:
采用上面的写法既实现了根据不同的条件执行不同的SQL,不过要注意:多了ALLOCATE和FREE两句。
void
TestIf()
{
EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx;
struct sqlca sqlca;
struct ConnectionInfo conn;
int n = 0;
int bln_value = 0;
EXEC SQL END DECLARE SECTION;
//获得连接
while (!conn.GetConn(&ctx))
{
P("获取连接失败!");
return;
}
EXEC SQL CONTEXT USE :ctx;
//=============================================================
if (bln_value)
{
EXEC SQL DECLARE CurTest CURSOR FOR
SELECT 1 FROM dual WHERE rownum<=1;
}
else
{
EXEC SQL DECLARE CurTest CURSOR FOR
SELECT 2 FROM dual WHERE rownum<=1;
}
EXEC SQL OPEN CurTest;
EXEC SQL FETCH CurTest INTO :n;
EXEC SQL CLOSE CurTest;
//=============================================================
P("n=%d", n);
return;
NO_WARNING;
}
{
EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx;
struct sqlca sqlca;
struct ConnectionInfo conn;
int n = 0;
int bln_value = 0;
EXEC SQL END DECLARE SECTION;
//获得连接
while (!conn.GetConn(&ctx))
{
P("获取连接失败!");
return;
}
EXEC SQL CONTEXT USE :ctx;
//=============================================================
if (bln_value)
{
EXEC SQL DECLARE CurTest CURSOR FOR
SELECT 1 FROM dual WHERE rownum<=1;
}
else
{
EXEC SQL DECLARE CurTest CURSOR FOR
SELECT 2 FROM dual WHERE rownum<=1;
}
EXEC SQL OPEN CurTest;
EXEC SQL FETCH CurTest INTO :n;
EXEC SQL CLOSE CurTest;
//=============================================================
P("n=%d", n);
return;
NO_WARNING;
}
以下的代码是根据if中的条件执行不同的查询。相信很多场合都需要根据不同的条件执行不同的SQL,这是一个普遍的需求。
然而,编译并执行这段代码,发现n的值始终是1,哪怕在if的条件中写上false(应该执行else部分),执行的结果还是1(如果执行到else部分,结果应该是2)。难道是没有执行到else部分?在if 和else部分分别加上不同的打印,发现程序的流程确实执行了else部分,但是始终只使用if中定义的SQL。
不知道这算不算PRO*C的一个BUG。打开proc.exe编译后的代码查看,发现sqlstm.stmt = "SELECT..."; 这样的代码只有一句。看来proc.exe预编译器在编译PC文件的时候,始终以第一个声明游标的SQL为准。
以上的代码说明:PRO*C中想要根据不同的条件执行不同的SQL,不能采用这样的写法。
如何解决呢?变换一下写法即可:
void
TestCursor()
{
EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx;
struct sqlca sqlca;
struct ConnectionInfo conn;
int n = 0;
SQL_CURSOR curTest;
int bln_value = 0;
EXEC SQL END DECLARE SECTION;
//获得连接
while (!conn.GetConn(&ctx))
{
P("获取连接失败!");
return;
}
EXEC SQL CONTEXT USE :ctx;
//=============================================================
EXEC SQL ALLOCATE :curTest;
if (bln_value)
{
EXEC SQL EXECUTE
BEGIN
OPEN :curTest FOR SELECT 1 FROM dual WHERE rownum<=1;
END;
END-EXEC;
}
else
{
EXEC SQL EXECUTE
BEGIN
OPEN :curTest FOR SELECT 2 FROM dual WHERE rownum<=1;
END;
END-EXEC;
}
EXEC SQL FETCH :curTest INTO :n;
EXEC SQL CLOSE :curTest;
EXEC SQL FREE :curTest;
//=============================================================
P("n=%d", n);
return;
NO_WARNING;
}
{
EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx;
struct sqlca sqlca;
struct ConnectionInfo conn;
int n = 0;
SQL_CURSOR curTest;
int bln_value = 0;
EXEC SQL END DECLARE SECTION;
//获得连接
while (!conn.GetConn(&ctx))
{
P("获取连接失败!");
return;
}
EXEC SQL CONTEXT USE :ctx;
//=============================================================
EXEC SQL ALLOCATE :curTest;
if (bln_value)
{
EXEC SQL EXECUTE
BEGIN
OPEN :curTest FOR SELECT 1 FROM dual WHERE rownum<=1;
END;
END-EXEC;
}
else
{
EXEC SQL EXECUTE
BEGIN
OPEN :curTest FOR SELECT 2 FROM dual WHERE rownum<=1;
END;
END-EXEC;
}
EXEC SQL FETCH :curTest INTO :n;
EXEC SQL CLOSE :curTest;
EXEC SQL FREE :curTest;
//=============================================================
P("n=%d", n);
return;
NO_WARNING;
}
采用上面的写法既实现了根据不同的条件执行不同的SQL,不过要注意:多了ALLOCATE和FREE两句。