plsql游标插入不同的模式
Posted
技术标签:
【中文标题】plsql游标插入不同的模式【英文标题】:plsql cursor insert into different schemas 【发布时间】:2017-07-17 09:33:59 【问题描述】:我有 2 张桌子。 第一个表包含许多教室的学生 (姓名、年龄、班级)
另一个表包含每个班级的模式(教室,模式名称)
(所以每个班级都有不同的模式)
所以我对每个班级都有不同的架构。我需要从学生表中获取所有数据并将它们复制到正确模式的目标表中。 (我以管理员身份登录,我可以访问所有架构)
这是我的声明:
DECLARE
CURSOR all_pupils
IS
SELECT NAME, AGE, CLAs-s-rOOM FROM TABLE_1
BEGIN
FOR pupil_rec
IN all_pupils
LOOP
EXECUTE IMMEDIATE 'INSERT INTO '
|| (Select schema_name FROM TABLE_2 sn WHERE sn.clas-s-room=pupil_rec.CLAs-s-rOOM) ||'.TARGET_TABLE '
||'(name, age) VALUES (pupil_rec.name, pupil_rec.age';
END LOOP;
END;
/
我收到此错误:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
我刚开始学习 PLSQL,有人告诉我必须用光标来学习。有人可以帮助我并告诉我这是否是正确的方法吗?我的结构似乎不正确..如何避免这些错误
【问题讨论】:
你不能在你喜欢的任何一行中间放一个(select ...)
。您需要扩展光标以包含所需的值。
【参考方案1】:
EXECUTE IMMEDIATE
仅适用于静态字符串。因此,您需要先将架构名称查询到一个变量中,然后将该变量包含在您的语句中。
游标的内容也不在执行字符串的范围内。所以你需要通过占位符来传递它的值。
DECLARE
CURSOR all_pupils
IS
SELECT NAME, AGE, CLAs-s-rOOM FROM TABLE_1;
l_schema_name varchar2(30);
BEGIN
FOR pupil_rec
IN all_pupils
LOOP
Select schema_name
into l_schema_name
FROM TABLE_2 sn
WHERE sn.clas-s-room=pupil_rec.CLAs-s-rOOM:
EXECUTE IMMEDIATE 'INSERT INTO '
|| l_schema_name ||'.TARGET_TABLE '
||'(name, age) VALUES (:1, :2)'
using pupil_rec.name, pupil_rec.age;
END LOOP;
END;
/
或者,在驱动光标中使用连接...
DECLARE
CURSOR all_pupils
IS
SELECT t1.NAME, t1.AGE, sn.schema_name
FROM TABLE_1 t1
join TABLE_2 sn
on sn.clas-s-room = T1.CLAs-s-rOOM
where t1.col_copied != 1
for update of t1.col_copied ;
BEGIN
FOR pupil_rec
IN all_pupils
LOOP
EXECUTE IMMEDIATE 'INSERT INTO '
|| pupil_rec.schema_name ||'.TARGET_TABLE '
||'(name, age) VALUES (:1, :2)'
using pupil_rec.name, pupil_rec.age;
update TABLE_1 t1
set t1.col_copied = 1
where current of all_pupils;
END LOOP;
END;
/
【讨论】:
我有一个额外的要求(抱歉,现在才发现)。我的 Table_1 有一个附加列 (COL_COPIED)。当该行被选择并复制到正确的模式中时,我需要将其设置为 1。因此,当再次执行该语句时,它只选择未复制的行(TABLE_1 将始终获取新数据)。我可以在我的 for 循环中执行一个附加语句(如插入)来进行更新吗?或者有没有更好的解决方案 非常感谢,只是一个问题(我试图理解您的陈述)您在开始时的连接会像您的第一个解决方案一样选择 table_1 中的所有数据(没有连接)。你刚刚使用了一个连接来引用循环内的 schema_name 对吗? 是的。一般来说,连接两个表比在循环中查找要好,因为集合操作比逐行处理更有效。这可能不会对您的情况产生太大影响,但养成好习惯永远不会太早 我在“当前的位置”行出现错误,它说缺少'('。并且此行不应以分号结尾:'(name,age)VALUES(:1,: 2)'; ? 嗯,不知道为什么您会收到 that 错误消息:您一定是打错字了。如果您正确翻译了我的示例,您将得到pls-00413
,因为我引用了记录变量而不是游标名称(自更正后)。【参考方案2】:
需要一个新变量来保存架构名称。在Execute Immediate
内不能连接其他SELECT
,除非它作为字符串提供。
DECLARE
CURSOR all_pupils
IS
SELECT NAME,
AGE,
CLAs-s-rOOM
FROM TABLE_1;
v_chr_schema TABLE_2.schema_name%TYPE;
BEGIN
FOR pupil_rec IN all_pupils
LOOP
SELECT schema_name
INTO v_chr_schema
FROM TABLE_2
WHERE sn.clas-s-room=pupil_rec.CLAs-s-rOOM;
EXECUTE IMMEDIATE 'INSERT INTO ' || v_chr_schema ||'.TARGET_TABLE ' ||
'(name, age) VALUES (' || pupil_rec.name || ',' || pupil_rec.age || ')';
END LOOP;
END;
/
【讨论】:
非常感谢,我根据您的输入更改了我的声明,但出现错误:00984. 00000 - “此处不允许列。 @Norbert94 - cursor 中的值应该在字符串之外。现在已在答案中修复以上是关于plsql游标插入不同的模式的主要内容,如果未能解决你的问题,请参考以下文章