创建一个列,然后使用PL / SQL程序向其中添加数据

时间:2019-01-10 10:04:00

标签: oracle plsql

我正在尝试创建一个PL / SQL程序,在该程序中我向表中添加一列(称为AGE_GROUP),然后将数据插入该列中,但它似乎不起作用。

    DECLARE
    cust_age string(10);
    cust_inc string(10);
    cust_status string(10);
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10));';
    FOR emp IN (SELECT *
                FROM datacopy) LOOP
        cust_age := get_group_age(emp.ID);
        cust_inc := get_income_level(emp.ID);
        cust_status := fix_status(emp.ID);
      UPDATE datacopy SET AGE_GROUP = cust_age WHERE ID = emp.ID;
      UPDATE datacopy SET INCOME_LEVEL = cust_inc WHERE ID = emp.ID;
      UPDATE datacopy SET MARITAL_STATUS = cust_status WHERE ID = emp.ID;
      COMMIT;
    END LOOP;
END; 

我看到的错误是错误报告- ORA-06550:第12行,第27列: PL / SQL:ORA-00904:“ AGE_GROUP”:不可接受的标识符

2 个答案:

答案 0 :(得分:3)

正如@Maxim所说,在解析PL / SQL块时,表中没有AGE_GROUP列,因此

UPDATE datacopy SET AGE_GROUP = cust_age WHERE ID = emp.ID;

引发您看到的ORA-00904错误。您还必须使该更新语句动态化,例如:

EXECUTE IMMEDIATE 'UPDATE datacopy SET AGE_GROUP = :1 WHERE ID = :2' USING cust_age, emp.ID;

但是您的游标查询也会遇到问题,因为在运行时,它不再与编译时的表定义匹配-因此SELECT *现在返回的列比预期的多。 (由此产生的错误是ORA-00932。)

您可以使整个光标循环动态化,但是由于仅使用ID列,因此不需要-只需选择该特定列即可,而不是选择*。当然,您应该只在所有代码中选择想要的列。

因此,要使其正常工作,您可以:

DECLARE
    cust_age string(10);
    cust_inc string(10);
    cust_status string(10);
BEGIN
    EXECUTE IMMEDIATE 'ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10))';
    FOR emp IN (SELECT ID
                FROM datacopy) LOOP
        cust_age := get_group_age(emp.ID);
        cust_inc := get_income_level(emp.ID);
        cust_status := fix_status(emp.ID);
        EXECUTE IMMEDIATE 'UPDATE datacopy SET AGE_GROUP = :cust_age WHERE ID = :id'
          USING cust_age, emp.ID;
        UPDATE datacopy SET INCOME_LEVEL = cust_inc WHERE ID = emp.ID;
        UPDATE datacopy SET MARITAL_STATUS = cust_status WHERE ID = emp.ID;
        COMMIT;
    END LOOP;
END;
/

尽管此代码还有很多其他问题。使用string(10)作为局部变量的数据类型不是Oracle-y,并且它们实际上并不是全部都是字符串-您可以将%TYPE用于表中已经存在的列。您不应该在循环内提​​交。当您可以一次设置所有三个列的值时,只需使用一条动态语句,就可以对同一行进行三个单独的更新,这似乎很浪费:

EXECUTE IMMEDIATE 'UPDATE datacopy SET AGE_GROUP = :cust_age,'
  || ' INCOME_LEVEL = :cust_inc,'
  || ' MARITAL_STATUS = :cust_status'
  || ' WHERE ID = :id'
  USING cust_age, cust_inc, cust_status, emp.ID;

当然,将ALTER作为一个简单的SQL语句(而不是在PL / SQL块之前)做起来要简单得多,

看起来您似乎根本就不需要PL / SQL,也不是逐行循环;您可以在进行静态更改后进行一次静态更新:

ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10));

UPDATE datacopy SET AGE_GROUP = get_group_age(ID),
  INCOME_LEVEL = get_income_level(ID),
  MARITAL_STATUS = fix_status(ID);

答案 1 :(得分:1)

这是因为首先解析该块,然后在没有错误的情况下才执行该块。因为在解析时datacopy表中没有age_group列,所以您会得到解析错误。您应该尝试使用动态SQL,引用游标。

并删除其中一个冒号,应为以下内容:

EXECUTE IMMEDIATE 'ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10))';