我们可以在SELECT查询中使用主机变量作为表名吗?

时间:2012-09-28 09:40:51

标签: sql c oracle oracle-pro-c

我正在尝试使用Pro * C代码。

我有3个表empmgrall;所有3个表格都包含emp_idemp_name。我尝试了以下代码,它给了我错误。如果有可能请告诉我?

const char table_name[3]={'emp','mgr','all'}
int counter = 0;
while(counter < 3)
{
 . . .
 EXEC SQL SELECT emp_name INTO :ename 
      From :table_name[counter++] 
      where emp_id=:emp_id;
}

我们可以为SELECTFROM使用变量吗?

2 个答案:

答案 0 :(得分:3)

这称为动态SQL:

使用此信息:

  

动态SQL

     

虽然嵌入式SQL适用于固定应用程序,但有时程序动态创建整个SQL语句非常重要   使用动态SQL,可以发出存储在字符串变量中的语句   PREPARE将字符串转换为SQL语句,EXECUTE执行该语句。请考虑以下示例。

   char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";
   EXEC SQL PREPARE q FROM :s;
   EXEC SQL EXECUTE q;
     

或者,PREPARE和EXECUTE可以合并为一个语句:

   char *s = "INSERT INTO emp VALUES(1234, 'jon', 3)";
   EXEC SQL EXECUTE IMMEDIATE :s;

来源:http://infolab.stanford.edu/~ullman/fcdb/oracle/or-proc.html

答案 1 :(得分:2)

不,我们不能使用host-variable为Pro * C中的静态SQL语句提供表名。

为Oracle 11.2g引用Oracle Pro*C Programmer's Guide

  

您不能使用输入主机变量来提供SQL关键字或数据库对象的名称。 [..]如果需要在运行时更改数据库对象名称,请使用动态SQL。另请参见第13章“Oracle Dynamic SQL”。

在Pro * C中,Oracle提供了不同的方法来执行SQL语句。主要区别在于静态和动态方法。而对于动态,有几种子方法允许不同的自由度。

静态SQL语句不是100%静态的 - 您可以在where子句表达式(作为操作数)中使用输入/输出主机变量,在insert语句中提供值,作为选择目标等。但是不要指定表名。这对于静态嵌入式SQL来说“过于动态”。

请注意,您仍然可以在动态准备的SQL语句中使用主机变量。建议这样做是为了避免SQL注入问题并提高性能(当语句执行多次时)。

示例(使用Oracle Dynamic SQL方法3):

const char *table_name[3] = {"emp", "mgr", "all"};
unsigned table_name_size = 0;
unsigned i = 0;
for (i = 0; i<table_name_size; ++i) {
    char stmt[128] = {0};
    snprintf(stmt, 128,
        "SELECT emp_name "
        "  FROM %s " 
        "  WHERE "
        "    emp_id = :emp_id",
      table_name[i]);

    EXEC SQL PREPARE emp_stmt FROM :stmt;
    // check sqlca.sqlcode ...
    EXEC SQL DECLARE emp_cursor CURSOR FOR emp_stmt;
    EXEC SQL OPEN emp_cursor USING :emp_id;
    // check sqlca.sqlcode ...
    EXEC SQL FETCH emp_cursor INTO :ename;
    // check sqlca.sqlcode ...
    EXEC SQL CLOSE emp_cursor;
    // check sqlca.sqlcode ...

    // ...
}