有人可以帮助我找到此过程中的错误吗?

时间:2019-11-15 03:38:03

标签: oracle stored-procedures plsql

我想知道此过程中的错误

set serveroutput on 
create or replace procedure insert_table(column_name in varchar2, dat in varchar2)
as
    table_name varchar2(100):= column_name || '_' || dat;
    sql_create varchar2(100) := 'create table '||table_name||'(FIRSTNAME varchar2(100))';
    sql_str varchar2(100);
    CURSOR c_emp is 
    select FIRSTNAME 
    from employees
    where column_name = dat;
begin
    execute immediate sql_create;
    for r_reg in c_emp
    loop
    sql_str:='INSERT INTO '||table_name||'('''||r_reg.firstname||''')';
    execute immediate sql_str;
    end loop;
end;
/
execute insert_table('CITY','London');

编辑: 好的,我在语法错误中添加了下面提到的更正,但是我该怎么做,以便可以在游标处获取列名的参数,因为目前它的类型为varchar,'CITY'应该是行名。

3 个答案:

答案 0 :(得分:1)

您将需要如下使用光标中的dynamic query。另外,您错过了我添加的VALUES语句中的INSERT关键字(请参阅代码中的内联注释)

Oracle示例数据创建:

SQL> CREATE TABLE "EMPLOYEES" (
  2      "ID"           NUMBER,
  3      "FIRSTNAME"    VARCHAR2(100 BYTE),
  4      "CITY"         VARCHAR2(100 BYTE),
  5      PRIMARY KEY ( "ID" ) USING INDEX ENABLE
  6  );

Table created.

SQL>

现在,让我们创建您的过程

SQL> CREATE OR REPLACE PROCEDURE INSERT_TABLE (
  2      COLUMN_NAME   IN            VARCHAR2,
  3      DAT           IN            VARCHAR2
  4  ) AS
  5
  6      TABLE_NAME   VARCHAR2(100) := COLUMN_NAME || '_' || DAT;
  7      SQL_CREATE   VARCHAR2(100) := 'create table ' || TABLE_NAME || '(FIRSTNAME varchar2(100))';
  8      C_EMP        SYS_REFCURSOR; -- declaration of cursor
  9      LV_FNAME     EMPLOYEES.FIRSTNAME%TYPE; -- to store the each value from cursor
 10  BEGIN
 11      EXECUTE IMMEDIATE SQL_CREATE;
 12      OPEN C_EMP FOR 'SELECT FIRSTNAME
 13                        FROM EMPLOYEES
 14                       WHERE ' || COLUMN_NAME || ' = ''' || DAT || '''';
 15      -- above statement used dynamic query in cursor
 16      LOOP
 17          FETCH C_EMP INTO LV_FNAME;
 18          EXIT WHEN C_EMP%NOTFOUND;
 19          EXECUTE IMMEDIATE 'INSERT INTO ' || TABLE_NAME || ' VALUES (''' || LV_FNAME || ''')'; -- added VALUES keyword in INSERT statement.
 20      END LOOP;
 21
 22      COMMIT;
 23  END INSERT_TABLE;
 24  /

让我们执行它并立即查看结果。

SQL>
SQL> EXECUTE INSERT_TABLE('CITY', 'London');

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL> SELECT * FROM CITY_LONDON;

FIRSTNAME
--------------------------------------------------------------------------------
TEJASH

SQL>

哦,是的,它创建了所需的表,并且正确填充了数据。

干杯!

答案 1 :(得分:0)

您缺少引号。这个

sql_str:='INSERT INTO '||table_name||'('||r_reg.firstname||');';

应该是

sql_str:='INSERT INTO '||table_name||'('''||r_reg.firstname||''');';

这会将INSERT INTO CITY_London (Peter);变成INSERT INTO CITY_London ('Peter');

根据文档(例如https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm):

  

在动态字符串中构造单个SQL语句时,请不要在引号内的末尾包括分号(;)。

因此EXECUTE IMMEDIATE的两个SQL字符串应为:

sql_create varchar2(100) := 'create table ' || table_name || '(FIRSTNAME varchar2(100))';

sql_str := 'INSERT INTO ' || table_name || '(''' || r_reg.firstname || ''')';

答案 2 :(得分:0)

这是您最后一个问题的答案。您可以像下面那样将参数传递给光标:

declare
    CURSOR c_emp(p_param varchar2) is 
    select p_param val
    from dual;
begin
    for r_reg in c_emp('b')
    loop
      dbms_output.put_line(r_reg.val);
    end loop;
end;