【问题标题】:Oracle MERGE and prepared statementOracle MERGE 和准备好的语句
【发布时间】:2013-07-16 08:20:45
【问题描述】:

我有一个备份实用程序,用于恢复部分。这是我的桌子:

CREATE TABLE "SBOOKS"."DEV_CORPUS" 
   (    "CORPUSID" NUMBER(9,0) NOT NULL ENABLE, 
    "CORPUS_NAME" VARCHAR2(768 BYTE) NOT NULL ENABLE, 
    "CORPUSLASTSYNC" DATE, 
     PRIMARY KEY ("CORPUSID")

在还原类中,我想在表中查找主键,如果存在则更新该行,如果不存在则插入一行。
现在的问题是我需要从类中传递参数(它们不存在于任何表中),我该怎么做?你的建议是什么?使用preparedstatement还是什么?如何?请提供示例或来源链接。

更多信息: 我正在使用 oracle sql developer 和 java netbeans。

编辑: 我正在命令窗口中尝试这个:

  MERGE INTO dev_corpus a  
  USING (SELECT corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain FROM dual WHERE corpusId = 1000156 AND corpus_name = 'sahar' AND corpusdesc = 'sahaaaaa' AND corpusimageids IS NULL AND rocf1 IS NULL AND rocf2 IS NULL AND rocf3 IS NULL AND rocc1 IS NULL AND rocc2 IS NULL AND rocc3 IS NULL AND corpusactive IS NULL AND corpusrunfrequency IS NULL AND corpuslastrun IS NULL AND corpuslastsync IS NULL AND rocsettingid IS NULL AND corpusaffinity IS NULL AND corpusterms IS NULL AND corpusdomain IS NULL) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpusid = incoming.corpusid , corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

这是真正的桌子:

CREATE TABLE "SBOOKS"."DEV_CORPUS" 
   (    "CORPUSID" NUMBER(9,0) NOT NULL ENABLE, 
    "CORPUS_NAME" VARCHAR2(768 BYTE) NOT NULL ENABLE, 
    "CORPUSDESC" VARCHAR2(4000 BYTE), 
    "CORPUSIMAGEIDS" VARCHAR2(768 BYTE), 
    "ROCF1" FLOAT(63), 
    "ROCF2" FLOAT(63), 
    "ROCF3" FLOAT(63), 
    "ROCC1" FLOAT(63), 
    "ROCC2" FLOAT(63), 
    "ROCC3" FLOAT(63), 
    "CORPUSACTIVE" NUMBER(3,0), 
    "CORPUSRUNFREQUENCY" NUMBER(3,0), 
    "CORPUSLASTRUN" DATE, 
    "CORPUSLASTSYNC" DATE, 
    "ROCSETTINGID" NUMBER(3,0), 
    "CORPUSAFFINITY" NUMBER(3,0), 
    "CORPUSTERMS" VARCHAR2(4000 BYTE), 
    "CORPUSDOMAIN" NUMBER(3,0), 
     PRIMARY KEY ("CORPUSID")

给我这个错误:

Error at Command Line:2 Column:644
Error report:
SQL Error: ORA-00904: "CORPUSDOMAIN": invalid identifier
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

我不知道我错过了什么。你有什么想法吗?

谢谢!

EDIT2: 最后这在命令 win 中起作用:

MERGE INTO dev_corpus a
  USING (SELECT 1000156 corpusid, 'sss2' corpus_name, 'sahaaaaaar' corpusdesc, null corpusimageids, null rocf1, null rocf2, null rocf3, null rocc1, null rocc2, null rocc3, null corpusactive, null corpusrunfrequency, null corpuslastrun, null corpuslastsync, null rocsettingid, null corpusaffinity, null corpusterms, null corpusdomain FROM dual) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

但这在 java 类 nooot 中适用于更新情况,但如果它是插入情况,它将起作用。在更新的情况下,它不会抛出任何错误,它只会冻结,直到我从数据库中删除记录,然后插入它,所以没有更新!。你发现这段代码有什么问题吗?

preparedStatement = dbConnection.prepareStatement("MERGE INTO dev_corpus a " +
                              "USING (SELECT ? corpusid, ? corpus_name, ? corpusdesc, ? corpusimageids, ? rocf1, ? rocf2, ? rocf3, ? rocc1, ? rocc2, ? rocc3, ? corpusactive, ? corpusrunfrequency, ? corpuslastrun, ? corpuslastsync, ? rocsettingid, ? corpusaffinity, ? corpusterms, ? corpusdomain FROM dual) incoming " +
                              "ON (a.corpusid = incoming.corpusid ) " +
                              "WHEN MATCHED THEN " +
                              "UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain " +
                              "WHEN NOT MATCHED THEN " +
                              "INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) " +
                              "VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)");

谢谢!

【问题讨论】:

  • 不清楚您使用的是 MySQL 还是 Oracle。您使用的是其中一个吗?或两者?如果您使用 Oracle,则需要 MERGE,如果您使用 MySQL,则需要 INSERT ... ON DUPLICATE KEY。至于语法问题,我发现最好在命令窗口中解决查询,然后当它看起来不错时,您可以在Java代码中实现它。
  • @Ed Gibbs:对不起,oracle sql 开发人员。请参阅上面的编辑代码。

标签: java mysql oracle prepared-statement insert-update


【解决方案1】:

终于成功了!所以这里是SQL命令的查询:

MERGE INTO dev_corpus a
  USING (SELECT 1000156 corpusid, 'sss2' corpus_name, 'sahaaaaaar' corpusdesc, null corpusimageids, null rocf1, null rocf2, null rocf3, null rocc1, null rocc2, null rocc3, null corpusactive, null corpusrunfrequency, null corpuslastrun, null corpuslastsync, null rocsettingid, null corpusaffinity, null corpusterms, null corpusdomain FROM dual) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

这是使用 pstmt 的 java 代码:

preparedStatement = dbConnection.prepareStatement("MERGE INTO dev_corpus a " +
                              "USING (SELECT ? corpusid, ? corpus_name, ? corpusdesc, ? corpusimageids, ? rocf1, ? rocf2, ? rocf3, ? rocc1, ? rocc2, ? rocc3, ? corpusactive, ? corpusrunfrequency, ? corpuslastrun, ? corpuslastsync, ? rocsettingid, ? corpusaffinity, ? corpusterms, ? corpusdomain FROM dual) incoming " +
                              "ON (a.corpusid = incoming.corpusid) " +
                              "WHEN MATCHED THEN " +
                              "UPDATE SET a.corpus_name = incoming.corpus_name , a.corpusdesc = incoming.corpusdesc , a.corpusimageids = incoming.corpusimageids , a.rocf1 = incoming.rocf1 , a.rocf2 = incoming.rocf2 , a.rocf3 = incoming.rocf3 , a.rocc1 = incoming.rocc1 , a.rocc2 = incoming.rocc2 , a.rocc3 = incoming.rocc3 , a.corpusactive = incoming.corpusactive , a.corpusrunfrequency = incoming.corpusrunfrequency , a.corpuslastrun = incoming.corpuslastrun , a.corpuslastsync = incoming.corpuslastsync , a.rocsettingid = incoming.rocsettingid , a.corpusaffinity = incoming.corpusaffinity , a.corpusterms = incoming.corpusterms , a.corpusdomain = incoming.corpusdomain " +
                              "WHEN NOT MATCHED THEN " +
                              "INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) " +
                              "VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)");

您在问题部分中有创建表,希望它可以帮助某人! :)

【讨论】:

    【解决方案2】:

    如果您使用的是 Oracle,那么您需要关注 MERGE 语句 - INSERT ... ON DUPLICATE KEY 在 Oracle 中不起作用。

    我不知道这是不是唯一的问题,但是您发布的MERGE 中有一些语法错误:

    MERGE INTO dev_corpus a
    USING (SELECT * FROM dual WHERE (corpusid=?, corpus_name=?, corpuslastsync=?)
                                    ^^^^^^^^^^^^^^^^^^^^^^ (1)
    ON (a.corpusid = incoming.corpusid )
    WHEN MATCHED THEN
    UPDATE SET (a.corpus_name = incoming.corpus_name AND a.corpuslastsync = incoming.corpuslastsync )
                ^^^^^^^^^^^^^^^^^^ (2)
    WHEN NOT MATCHED THEN
    INSERT (a.corpusid, a.corpus_name, a.corpuslastsync)
    VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpuslastsync)
    

    问题(1):你有一个不闭合的括号,加上多个WHERE条件应该用AND分隔,而不是逗号。这是更正的版本,缩进,因此不需要水平滚动:

    USING (
      SELECT * FROM dual
      WHERE (corpusid=? AND corpus_name=? AND corpuslastsync=?))
    

    在这种情况下,WHERE 条件周围的括号是可选的,所以这也可以:

    USING (
      SELECT * FROM dual
      WHERE corpusid=? AND corpus_name=? AND corpuslastsync=?)
    

    问题(2):SET 后面的括号,这里你需要逗号而不是AND。它应该看起来像这样(如上所述,我已经缩进了它,所以它可以在没有水平滚动的情况下阅读)

    UPDATE SET
      a.corpus_name = incoming.corpus_name,
      a.corpuslastsync = incoming.corpuslastsync
    

    这应该会处理任何语法错误,但当然这并不能保证您的结果会如预期的那样:)

    最后,正如我在 cmets 中提到的,在 SQLPlus 或 SQL Developer 中使用测试值(而不是参数)尝试一下。这样调试会容易得多。当MERGE 行为正确时,您可以将其移至Java 代码并对其进行参数化。祝你好运!


    更新问题的附录

    首先,好消息您正在使用 SQL Developer 来解决这个问题!忽略我上面的最后一段:)

    其次,您的位置包括AND corpuslastsync = null。检查null时,需要IS NULL,而不是= NULL

    ... AND corpuslastsync IS NULL
    

    最后,我很确定您最近一次尝试遇到的具体错误是由于这一行的别名:

    INSERT (a.corpusid, a.corpus_name, a.corpuslastsync)
    

    试试这个:

    INSERT (corpusid, corpus_name, corpuslastsync)
    

    Oracle 知道这里命名的列属于dev_corpus 表,别名为a

    【讨论】:

    • 非常感谢。但还是不行 :(。请看编辑后的问题
    • 您可以尝试删除UPDATE 部分上的a. 别名吗?而不是SET a.corpusid = incoming.corpusid, etc 尝试SET corpusid = incoming.corpusid
    • 再次但仍然不起作用,但另一个错误,请查看编辑后的查询。
    • 到达那里!新错误是因为您从第二行的DUAL 中进行选择,而DUAL 没有corpusdomain 列或SELECT 列表中的任何其他列。
    • 链接上的内容看起来很可靠,尽管我会像我们在这里所做的那样去除别名。在这种情况下,您肯定会从DUAL 中进行选择。你想要这样的东西(部分示例!):... USING (SELECT 12345 corpusid, 'The name' corpus_name, 'The desc' corpusdesc FROM DUAL WHERE ...)
    猜你喜欢
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多