PL/SQL 插入使用多个选择和减号运算符
Posted
技术标签:
【中文标题】PL/SQL 插入使用多个选择和减号运算符【英文标题】:PL/SQL insert using multiple selects and minus operator 【发布时间】:2016-08-19 15:04:50 【问题描述】:以下作品:
INSERT INTO BASE_TABLE
(
req,
desc,
ver
)
SELECT * FROM UPDATE_TABLE
minus
SELECT req, desc, ver FROM BASE_TABLE;
但是,这会导致错误(只是尝试再插入一个字段:'key'):
INSERT INTO BASE_TABLE
(
req,
desc,
ver,
key
)
SELECT * FROM UPDATE_TABLE
minus
SELECT req, desc, ver FROM BASE_TABLE,
SELECT CONCAT(req, ver) FROM UPDATE_TABLE;
错误:
PL/SQL:ORA-00903:无效的表名
尝试通过从 UPDATE 表中选择尚未在 BASE_TABLE 中的所有内容来将行插入到 BASE_TABLE 中。只是想添加“关键”字段。
最后一个 SELECT 似乎不合适并导致此错误。 'SELECT ...减去SELECT ...'是否等于一条语句,因此需要将第三条SELECT语句分开?但是怎么做呢?
【问题讨论】:
看看MERGE
- 当您需要比较INSERT
的两个表时,它可能会好得多。
一些注意事项/问题:首先,您将不能使用DESC
和KEY
作为列名(它们是无效的对象名,因为它们是Oracle 保留字)。在您的实际数据中,您可能有其他名称,但对于测试 DESC
和 KEY
将不起作用。然后,在 Oracle 中 concat()
非常有限(例如它只需要两个参数),你最好使用 ||
操作符来做同样的事情。那么,你的req
和ver
是什么数据类型呢?如果不是字符数据类型,Oracle会隐式转换,是你想要的吗?
另外,你连接 req 和 ver 没有分隔符;那是一种奇怪的钥匙。 req=1,ver=23
将与 req=12,ver=3
具有相同的密钥 - 这是您需要的吗?
感谢 mathguy,我看看 MERGE。把真名拿出来,当然是保留字了:)req是唯一值,这里应该不错。
我发布了两个解决方案(它们完全不同,所以我没有将它们显示为一个答案)。其中一个不使用 MERGE,它只是修复了您最初的尝试。 (我认为 - 我没有测试它。)
【参考方案1】:
要使其按原样工作,您的最后一个“SELECT”实际上应该转到外部查询,如下所示:
INSERT INTO BASE_TABLE
(
req,
desc,
ver,
key
)
SELECT req, desc, ver, CONCAT(req, ver)
FROM
( SELECT * FROM UPDATE_TABLE
minus
SELECT req, desc, ver FROM BASE_TABLE
);
注意:这是一个“懒惰”的解决方案,应该没有SELECT *
,列名应该完整拼写。我只是按照您的指示... 现在,UPDATE_TABLE
应该具有正确的列数、正确的名称和正确的顺序,因为您说您的第一个查询有效(否则它将无法正常工作)。但是如果以后你在UPDATE_TABLE
中添加一列,SELECT *
的查询将不再起作用,但全列名的查询不会受到影响。
【讨论】:
此方法出错:PL/SQL: ORA-01789: 查询块的结果列数不正确 对不起,是的 - 让我来解决它。 (减号仍然需要一个子查询!) 当我看到“减号”运算符时,我的眼睛抽搐了一下。第一次使用 pl/sql。 真的是 SQL,而且是标准的 SQL。MINUS
操作是基本的集合论操作,应该存在于任何关系数据库和语言标准中。
还没有真正遇到过。我在这里向另一位开发人员展示了这个问题,他也没有看到。也许不常见?也许您的合并方法是解决此类问题的干净方法?【参考方案2】:
基于 mus shou 的两个选择包含相同数量和类型的列
尝试使用
SELECT req, desc, ver FROM UPDATE_TABLE
minus
SELECT req, desc, ver FROM BASE_TABLE
【讨论】:
【参考方案3】:MERGE
解决方案:插图
文档在这里:https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm
我创建了两个小桌子来进行说明。请参阅我对原始帖子的评论:desc
和 key
是保留字,因此它们不能用作列名,我相应地更改了它们。我使用||
运算符进行连接并显式转换为字符数据类型(VARCHAR2
)。
创建小型测试表:
create table base_table ( req, dscr, ver, ky ) as
select 1, 'alpha', 235, '1235' from dual union all
select 2, 'beta' , 33 , '233' from dual
;
select * from base_table;
REQ DSCR VER KY
---------- ----- ---------- ----
1 alpha 235 1235
2 beta 33 233
create table update_table (req, dscr, ver) as
select 1, 'alpha', 235 from dual union all
select 5, 'rho' , 444 from dual
;
select * from update_table;
REQ DSCR VER
---------- ----- ----------
1 alpha 235
5 rho 444
MERGE
解决方案和结果:
merge into base_table b
using update_table u
on (b.req = u.req and b.dscr = u.dscr and b.ver = u.ver)
when not matched then
insert ( req, dscr, ver, ky )
values ( u.req, u.dscr, u.ver, to_char(u.req) || to_char(u.ver) )
;
select * from base_table;
REQ DSCR VER KY
---------- ----- ---------- ----
1 alpha 235 1235
2 beta 33 233
5 rho 444 5444
【讨论】:
以上是关于PL/SQL 插入使用多个选择和减号运算符的主要内容,如果未能解决你的问题,请参考以下文章
=> 在 oracle pl sql.is 和调用运算符中是啥意思?