Pro *C 查询 IN 子句中的多个动态值

Posted

技术标签:

【中文标题】Pro *C 查询 IN 子句中的多个动态值【英文标题】:Multiple dynamic values in a Pro *C query IN clause 【发布时间】:2014-04-07 16:21:51 【问题描述】:

我想读取一个平面文件来获取一个动态的值列表(值的数量不固定)然后我想在 Pro *C 中选择查询的 IN 子句中使用这个值列表。使用 Pro *C 实现这一目标的最佳方法是什么?我遇到了一些有用的文章here 和here,但我只想检查是否有更适合我的用例的解决方案。权衡我可能拥有的选项的利弊也很有用。

举个例子,下面是查询:

SELECT ca.co_id
INTO :host_co_id_1
FROM contr1 ch1, contr2 ca
WHERE ch_seqno = (SELECT MAX (ch_seqno) FROM ontr1 ch2
WHERE ch1.co_id = ch2.co_id)
and ch1.ch_status IN ('a','s')
AND ca.co_id = ch1.co_id
AND ca.tmcode IN (14,16,36,37,38,39,40,41,42,79,60);

号码列表:

14,16,36,37,38,39,40,41,42,79,60

是从文件中读取的动态列表。

【问题讨论】:

我想您可以使用collections,但从文档中看不出您如何(或是否)可以将其用作 ProC 中的table() 目标。 (类似于this approach in Java)。也许您需要object type translator 功能。似乎它*应该比这更简单...... @ThinkJet 有shown how to do this with OCI;您也许可以使用它或将其改编为 Pro*C? 【参考方案1】:

这可以使用Oracle Dynamic SQL:Method 4。 演示中包含的sample10.pc 说明了这种方法。 示例代码如下 变量stmt 可以从带有多个动态值的IN 子句的文件中读取。

 /*
* A very simple program that demonstrates how to do
* array fetches using dynamic SQL Method 4.
* file name: sample.pc
* environment: Win 7,code::blocks(mingw/gcc),oracle 11g(on solaris)
* Make sure to precompile with MODE=ORACLE.
example:
C:\oracle_instant_client\instantclient_11_2\sdk\proc.exe DYNAMIC=ORACLE C:\code\sample.pc
*/

#include <stdio.h> 
#include <stdlib.h>
#include <oci.h>

EXEC SQL INCLUDE sqlcpr;
EXEC SQL INCLUDE sqlda;
EXEC SQL INCLUDE oraca;
EXEC SQL INCLUDE sqlca;

#define MAX_SELECT_ITEMS   15
#define FETCH_SIZE         100  /* Fetch in 100 row chunks. */
#define MAX_CHARS          20   /* Change this for max colume size */
#define MAX_NAME_SIZE      20  /* Maximum size of a select-list item name. */

SQLDA   *selda; 

/* Data buffer. */
char c_data[MAX_SELECT_ITEMS][FETCH_SIZE][MAX_CHARS];

void print_rows(n)
int n;

int row, sli;

for (row = 0; row < n; row++)

    for (sli = 0; sli < selda->N; sli++)
    
        printf("%.20s ", c_data[sli][row]);
    
   printf("\n");



EXEC SQL BEGIN DECLARE SECTION;
int array_size = FETCH_SIZE;  /* needs to be a host var for FOR */
char *username = "ORACLE_USER/ORACLE_PASS";
char sid[]="ORACLE_SID";
char *stmt = "select t.a,t.b,t.c,p.d,t.e,t.f,t.g,t.h,t.i,t.j from table_t t,table_p p where p.error_code = t.error_code and rownum <= 50";
EXEC SQL END DECLARE SECTION;


void sql_error()

char msgbuf[512];/*
size_t msgbuf_len, msg_len;

msgbuf_len = sizeof(msgbuf);
sqlglm(msgbuf, &msgbuf_len, &msg_len);

printf ("\n\n%.*s\n", msg_len, msgbuf);*/

EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK WORK RELEASE;
exit(EXIT_FAILURE);


void main() 
 
int row_count;
int sli;     /* select-list item */

EXEC SQL CONNECT :username USING :sid; 
if (sqlca.sqlcode == 0)
printf("Connected.\n"); 
else

printf("Connection failed.\n");
exit(EXIT_FAILURE);


EXEC SQL WHENEVER SQLERROR DO sql_error();


selda = SQLSQLDAAlloc (SQL_SINGLE_RCTX, MAX_SELECT_ITEMS, MAX_NAME_SIZE, 0);

EXEC SQL PREPARE S FROM :stmt;
EXEC SQL DECLARE C CURSOR FOR S;
EXEC SQL OPEN C;
EXEC SQL DESCRIBE SELECT LIST FOR S INTO selda;

selda->N = selda->F;   /* Assumed not negative. */
for (sli = 0; sli < selda->N; sli++)

    /* Set addresses of heads of the arrays in the V element. */
    selda->V[sli] = c_data[sli][0];
    /* Convert everything to varchar on output. */
    selda->T[sli] = 1;
    /* Set the maximum lengths. */
    selda->L[sli] = MAX_CHARS;


for (row_count = 0; ;)

    /* Do the fetch. The loop breaks on NOT FOUND. */
    EXEC SQL FOR :array_size FETCH C USING DESCRIPTOR selda;

    print_rows(sqlca.sqlerrd[2] - row_count);
    row_count = sqlca.sqlerrd[2];
    if (sqlca.sqlcode == 1403)
    break;


/*    if (sqlca.sqlerrd[2] - row_count > 0)
print_rows(sqlca.sqlerrd[2] - row_count); */

printf("\n%d rows retrieved\n", sqlca.sqlerrd[2]);

EXEC SQL ROLLBACK RELEASE;
exit(EXIT_SUCCESS);

【讨论】:

以上是关于Pro *C 查询 IN 子句中的多个动态值的主要内容,如果未能解决你的问题,请参考以下文章

IN 子句中的多个列 Apache Derby

MySQL中的空IN子句参数列表

如何将 select 语句的 IN 子句中的参数作为具有多个值的参数传递?

where 子句中的动态值

MySQL“IN”子句中的逗号分隔值

仅存储多个用户生成值中的第一个的动态分配数组