【问题标题】:PL/SQL insert using multiple selects and minus operatorPL/SQL 插入使用多个选择和减号运算符
【发布时间】: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 的两个表时,它可能会好得多。
  • 一些注意事项/问题:首先,您将不能使用DESCKEY 作为列名(它们是无效的对象名,因为它们是Oracle 保留字)。在您的实际数据中,您可能有其他名称,但对于测试 DESCKEY 将不起作用。然后,在 Oracle 中 concat() 非常有限(例如它只需要两个参数),你最好使用 || 操作符来做同样的事情。那么,你的reqver是什么数据类型呢?如果不是字符数据类型,Oracle会隐式转换,是你想要的吗?
  • 另外,你连接 req 和 ver 没有分隔符;那是一种奇怪的钥匙。 req=1,ver=23 将与 req=12,ver=3 具有相同的密钥 - 这是您需要的吗?
  • 感谢 mathguy,我看看 MERGE。把真名拿出来,当然是保留字了:)req是唯一值,这里应该不错。
  • 我发布了两个解决方案(它们完全不同,所以我没有将它们显示为一个答案)。其中一个不使用 MERGE,它只是修复了您最初的尝试。 (我认为 - 我没有测试它。)

标签: oracle plsql oracle-apex


【解决方案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

    我创建了两个小桌子来进行说明。请参阅我对原始帖子的评论:desckey 是保留字,因此它们不能用作列名,我相应地更改了它们。我使用|| 运算符进行连接并显式转换为字符数据类型(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
    

    【讨论】:

      猜你喜欢
      • 2019-02-02
      • 2014-08-05
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-01
      相关资源
      最近更新 更多