表名是动态传进去的,请问可以建这样的function吗?
function参数为表名,ID和字段名;
里面利用这个表名拼一个SQL语句取出该字段的值用游标执行将结果fetch出来返回。
function中的SQL串是不是不能拼表名和字段,只能拼字段的值?大家能不能帮帮我,应该怎么弄,万分感谢!!!

解决方案 »

  1.   

    create or replace function fun(v_table in varchar2,
                                   id      in number,
                                   v_col   in varchar2)
    return   varchar2 
    is 
       v varchar2(2000);
       
    begin    execute immediate 'select '||v_col||' from '||v_table||' where id = '||id into v;
       return v;
    end fun;
    /
      

  2.   

    应该没问题的吧,
    你是的动态SQL,是不是指 ref cursor
      

  3.   


    编译的时候没问题,但是执行的时候说这一行
    execute immediate 'select '||v_col||' from '||v_table||' where id = '||id into v;
    无效的SQL语句。是怎么回事啊
      

  4.   

    我是想用ref cursor来着,也是同一个错误,说是无效SQL语句
      

  5.   

    你把这个语句打印出来,然后拿到SQLPLUS里面执行看看。有没有错误
      

  6.   


    嗯,试了我把function改成返回这个拼的SQL语句,然后拿到PL/SQL里能执行有结果不报错
      

  7.   

    v_sql := 'select ...'dbms_output.put_line(v_sql)用单步调试看看 然后把 v_sql的内容放到 sqlplus或PL/SQL里面执行
      

  8.   

    SQL> set serveroutput on
    SQL> 
    SQL> create or replace function fun(v_table in varchar2,
      2                                 id      in number,
      3                                 v_col   in varchar2)
      4  return   varchar2
      5  is
      6     v varchar2(2000);
      7  
      8  begin
      9  
     10     execute immediate 'select '||v_col||' from '||v_table||' where id = '||id into v;
     11     return v;
     12  end fun;
     13  /Function createdSQL> create table a(id number, name varchar2(20));Table createdSQL> insert into a values(10,'xxx');1 row insertedSQL> 
    SQL> declare
      2   v varchar2(20);
      3  begin
      4    v:= fun('a',10,'name');
      5    dbms_output.put_line(v);
      6  end;
      7  /xxxPL/SQL procedure successfully completedSQL> 返回多列需要用ref cursor
      

  9.   

    噢,错了,是返回多行记录需要用到ref cursor
      

  10.   

    你帮我看一下,这是我的
    CREATE OR REPLACE FUNCTION process_node_info (
      table_id IN NUMBER,
      record_id IN NUMBER
    ) RETURN NVARCHAR2 AS
      table_name NVARCHAR2(50);--表名
      --doc_type NVARCHAR2(30);--状态(先不管)
      doc_no NVARCHAR2(30);--文档号(先返回这个)
      sql_str NVARCHAR2(300);
    BEGIN
      --ad_table里记录了表的信息,这里取得表名
      EXECUTE IMMEDIATE 'SELECT t.tablename FROM ad_table t where t.ad_table_id='||table_id INTO table_name;
      --sql_str := 'SELECT documentno FROM '||table_name||' where '||table_name||'_id ='||record_id;
      
      --根据表名和ID去到得documentno的值。我传进来的表里面肯定有这个字段。
      --我的表的ID取名规则都是“表名_ID”
      EXECUTE IMMEDIATE 'SELECT documentno FROM'||table_name||'where'||table_name||'_id='||record_id into doc_no;
      return doc_no;END process_node_info;我测试的时候说第二个EXECUTE IMMEDIATE 无效的SQL语句。
      

  11.   

    FROM后面和WHERE和两边都是有空格的,复制进来后为了显示作了一些调整
      

  12.   

    dbms_output.put_line(sql_str);
    execute immediate sql_str into doc_no;用这种方式单步调试
      

  13.   


    注意使用动态sql语句的时候,空格问题是错误高发问题
      

  14.   

    我是感觉应该是你SQL语句问题
      

  15.   

    好像这样的话编译通不过
    这一句:execute immediate sql_str into doc_no; 
    焦点在  sql_str  ,说表达式类型错误。
      

  16.   

    SQL语句应该没问题,因为我把返回值改成sql_str而不是doc_no,把第二个execute immediate注释掉,然后执行这个function得到的结果也就是SQL语句复制下来,执行是正确的
      

  17.   

    CREATE OR REPLACE FUNCTION process_node_info ( 
      table_id IN NUMBER, 
      record_id IN NUMBER 
    ) RETURN NVARCHAR2 AS 
      table_name NVARCHAR2(50);--表名 
      --doc_type NVARCHAR2(30);--状态(先不管) 
      doc_no VARCHAR2(30);--文档号(先返回这个) 
      v_sql varchar2(2000);
    BEGIN 
      dbms_output.put_line('SELECT t.tablename FROM ad_table t where t.ad_table_id='||table_id);
      EXECUTE IMMEDIATE 'SELECT t.tablename FROM ad_table t where t.ad_table_id='||table_id INTO table_name; 
      --sql_str := 'SELECT documentno FROM '||table_name||' where '||table_name||'_id ='||record_id; 
      
      v_sql  := 'SELECT documentno FROM '||table_name||' where '||table_name||'_id ='||record_id;
      dbms_output.put_line(v_sql);
      EXECUTE IMMEDIATE v_sql  into doc_no; 
      return doc_no; END process_node_info; 
    /
      

  18.   

    注意类型对应sql字符串varchar2(2000),没汉字少用nvarchar
    SQL> 
    SQL> declare
      2    v NVARCHAR2(50);
      3  begin
      4   v := process_node_info(4,1);
      5   dbms_output.put_line(v);
      6  end;
      7  /SELECT t.tablename FROM ad_table t where t.ad_table_id=4
    SELECT documentno FROM a where aid =1
    xxxxxxxxxxPL/SQL procedure successfully completed
      

  19.   

    嗯,出来了,谢谢shiyiwan,谢谢灰尘,还有书虫的提醒。
    剩下的我自己搞定!