Oracle 创建一个列,然后使用PL/SQL程序向其中添加数据
我试图创建一个PL/SQL程序,在其中向表中添加一个列(称为AGE_GROUP),然后向该列中插入数据,但它似乎不起作用Oracle 创建一个列,然后使用PL/SQL程序向其中添加数据,oracle,plsql,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
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:“年龄组”:不可接受的标识符这是因为首先解析块,只有在没有错误时才执行块。您会得到解析错误,因为在解析时datacopy表中没有年龄组列。您应该尝试使用动态SQL,ref cursor 并删除其中一个冒号,它应为以下内容:
EXECUTE IMMEDIATE 'ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10))';
这是因为首先解析块,然后在没有错误的情况下执行。您会得到解析错误,因为在解析时datacopy表中没有年龄组列。您应该尝试使用动态SQL,ref cursor 并删除其中一个冒号,它应为以下内容:
EXECUTE IMMEDIATE 'ALTER TABLE DATACOPY ADD(AGE_GROUP VARCHAR2(10))';
正如@Maxim所说,在解析PL/SQL块时,表中没有
AGE\u GROUP
列,因此
UPDATE datacopy SET AGE_GROUP = cust_age WHERE ID = emp.ID;
抛出您看到的ORA-00904错误。您还必须使update语句动态,例如:
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块内部执行
不过,看起来您根本不需要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);
正如@Maxim所说,在解析PL/SQL块时,表中没有
AGE\u GROUP
列,因此
UPDATE datacopy SET AGE_GROUP = cust_age WHERE ID = emp.ID;
抛出您看到的ORA-00904错误。您还必须使update语句动态,例如:
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块内部执行
不过,看起来您根本不需要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);