该值未正确存储在数组中
Posted
技术标签:
【中文标题】该值未正确存储在数组中【英文标题】:the value is not storing properly in an array 【发布时间】:2016-10-04 08:31:48 【问题描述】:我有一个 define_Variable.sql 文件并包含
DEFINE T_SCHEMA='HR';
2) Create_table.sql
@define_variable.sql
DECLARE
TYPE table_array IS TABLE OF VARCHAR2(200);
table_list table_array;
l_query varchar2(500);
is_exst number :=0;
nt_exst number :=0;
BEGIN
l_query:= 'select TABLE_NAME from DBA_tables WHERE OWNER = :OWNER and TABLE_NAME IN (''employee'',''appraisal'')';
execute immediate l_query BULK COLLECT INTO table_list USING '&T_SCHEMA' ;
DBMS_OUTPUT.PUT_LINE('Total Tables to be deployed is :'||table_list.count);
IF 'employee' member of table_list THEN
DBMS_OUTPUT.PUT_LINE('employee TABLE ALREADY EXISTS');
ELSE
Execute Immediate(' create table employee( id number,name varchar2(50))');
DBMS_OUTPUT.PUT_LINE('employee TABLE created');
end if;
end;
/
当我执行脚本时,它将检查表是否存在条件,如果存在,它将显示消息为“已经存在”,否则,它将创建一个表。 所以任何时候,我的脚本都可以执行而不会抛出错误。
现在,问题是,当我运行脚本时,由于名称已经存在,它会抛出错误,数组 table_list.count 的计数显示为零。它将变为 else 条件而不是 IF 条件。可能是什么原因?
【问题讨论】:
为什么在检查表是否已经存在时指定schema名称,而在创建表时不指定?它将在当前模式中创建它,这可能与&T_SCHEMA
不同。如果它始终是当前模式,您可以简化代码,因为您不需要变量。或者通过尝试创建表来进一步简化它,并根据需要处理 ORA-00955 name is already used 异常。
***.com/help/someone-answers
【参考方案1】:
当你这样做时
create table employee( id number,name varchar2(50))
表名是not a quoted identifier(这很好!),数据字典中的对象名将是大写的EMPLOYEE
。
当您查询数据字典时,名称需要与该大小写匹配:
l_query:= 'select TABLE_NAME from DBA_tables WHERE OWNER = :OWNER and TABLE_NAME IN (''EMPLOYEE'',''APPRAISAL'')';
当你查看集合时,它也需要是大写的:
IF 'EMPLOYEE' member of table_list THEN
您的USING
子句看起来也有问题;
USING '.&T_SCHEMA.' ;
意味着它将查找所有者值'.HR'
,而不仅仅是'HR'
,除非您已努力创建名称中带有点的新模式(作为带引号的标识符),否则将与该所有者无关。您已经使用了一个尾随点来 - 大概 - 终止替换变量名称,这很好,但在这里并不严格要求。你不应该有一个前导点:
USING '&T_SCHEMA.' ;
因此,目前您正在使用不存在的所有者名称和表名称填充您的集合,因为它们与数据字典中的实际内容不匹配。
【讨论】:
嗨,Alex,感谢 cmets,我尝试使用大写字母,但它不起作用。我的实时项目有超过 15 个表,尽管某些表已经存在,但数组显示为空。 您是否也修复了替换中的前导点?如果你有set verify on
,你可以确切地看到替换在做什么。
哇,它有效,我相信它使用尾随点的错误,解决了我的问题亚历克斯。非常感谢
The trailing dot is OK - 虽然没有必要。前导点不对。【参考方案2】:
或者,您可以使用以下方法来实现您的目标:
DECLARE
TYPE table_array IS TABLE OF VARCHAR2 (200);
table_list table_array;
l_query VARCHAR2 (500);
is_exst NUMBER := 0;
nt_exst NUMBER := 0;
BEGIN
l_query :=
'select TABLE_NAME from DBA_tables WHERE OWNER = :OWNER and TABLE_NAME IN (''EMPLOYEE'',''appraisal'')';
EXECUTE IMMEDIATE l_query BULK COLLECT INTO table_list USING '&T_SCHEMA.';
DBMS_OUTPUT.PUT_LINE (
'Total Tables to be deployed is :' || table_list.COUNT);
for i in 1..table_list.count
loop
IF table_list(i) = 'EMPLOYEE' THEN
DBMS_OUTPUT.PUT_LINE ('employee TABLE ALREADY EXISTS');
ELSE
EXECUTE IMMEDIATE
(' create table employee( id number,name varchar2(50))');
DBMS_OUTPUT.PUT_LINE ('employee TABLE created');
END IF;
end loop;
--
-- IF 'employee' MEMBER OF table_list
-- THEN
-- DBMS_OUTPUT.PUT_LINE ('employee TABLE ALREADY EXISTS');
-- ELSE
-- EXECUTE IMMEDIATE
-- (' create table employee( id number,name varchar2(50))');
--
-- DBMS_OUTPUT.PUT_LINE ('employee TABLE created');
-- END IF;
END;
/
【讨论】:
如果employee
和appraisal
都存在,则表数为2;假设他们按照这个顺序,当i=1
它将看到该员工已经存在并报告它。当i=2
的值将是'APPRAISAL'
,所以它仍然会尝试再次创建员工表。
@XING,感谢您的帮助
@AlexPoole.我猜 OP 刚刚询问了一个示例,说明他为什么动态创建员工表。在实际场景中,它应该是动态的。
@AnishGopinath ..尽管亚历克斯所说的是正确的,但我只是为您的工作提供了一个替代方案。你所做的也是正确的。以上是关于该值未正确存储在数组中的主要内容,如果未能解决你的问题,请参考以下文章