【问题标题】:Oracle PLS-00103 error. How do you check for an existing record and do update or insert based on that condition?Oracle PLS-00103 错误。您如何检查现有记录并根据该条件进行更新或插入?
【发布时间】:2010-11-30 14:11:55
【问题描述】:

我需要通过 SELECT 语句检查表中是否存在记录。如果记录存在,则进行更新,否则在表上创建记录。我正在尝试,但我收到 PLS-00103 错误。

这些是我在 DBVisaulzier 中运行代码时遇到的错误:

18:00:09  [DECLARE - 0 row(s), 0.000 secs]  [Error Code: 6550, SQL State: 65000]  ORA-06550: line 2, column 12:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

:= . ( @ % ; not null range default character
18:00:09  [BEGIN - 0 row(s), 0.000 secs]  [Error Code: 6550, SQL State: 65000]  
ORA-06550: line 2, column 97:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

;
18:00:09  [IF - 0 row(s), 0.000 secs]  [Error Code: 900, SQL State: 42000]  ORA-00900: invalid SQL statement
18:00:09  [ELSE - 0 row(s), 0.000 secs]  [Error Code: 900, SQL State: 42000]   
ORA-00900: invalid SQL statement
18:00:09  [END - 0 row(s), 0.000 secs]  [Error Code: 900, SQL State: 42000]  ORA-00900: invalid SQL statement
18:00:09  [END - 0 row(s), 0.000 secs]  [Error Code: 900, SQL State: 42000]  ORA-00900: invalid SQL statement
... 6 statement(s) executed, 0 row(s) affected, exec/fetch time: 0.000/0.000 sec  [0 successful, 0 warnings, 6 errors]

以下是我的代码:

DECLARE a NUMBER;

BEGIN

  SELECT 1 
    INTO a 
    FROM FREC_EMAIL t
   WHERE t.FranchiseNo = '208254846' 
     AND t.ReportID = 1 
     AND t.id = 165;

  IF a=1 THEN

       UPDATE FREC_EMAIL
          SET email = 'blah@foo.com'
        WHERE FranchiseNo = '208254846' 
          AND ReportID = 1 
          AND ID = 165;

    ELSE

        INSERT INTO FREC_EMAIL
          (FranchiseNo, Email, ReportID)
         VALUES
           ('208254846', 'blah@foo.com', 1);

    END IF;
END;

【问题讨论】:

  • 考虑使用 MERGE 语句。
  • 你能举个例子吗?很抱歉问这个问题,但我是 PL/SQL 的新手。
  • 看起来编译器在抱怨几件事。您可以尝试将 SELECT 1 INTO a 更改为 SELECT ID INTO a 吗?
  • ORA 错误指向尝试运行无效的 SQL 语句。 “SELECT 1 INTO a...”没有任何问题 - 我相信问题是由于 Jack 试图将其作为匿名 sproc 运行。可能是 SQLPlus 末尾缺少“/”的问题...

标签: sql oracle plsql upsert ora-00900


【解决方案1】:

我们应该尽可能使用 SQL,除非绝对必要,否则避免使用 Pl/SQL。 SQL 语句执行得更快,它们通常需要更少的输入,并且更容易正确。

自 9i 以来,Oracle 提供了 MERGE,即执行“upsert”语句的单个 SQL 语句。

MERGE INTO frec_email t
USING (SELECT  'blah@foo.com' as email
                ,  '208254846' as FranchiseNo
                , 1 as ReportID
                , 165 as ID 
       FROM dual ) s
ON (s.ID = t.ID)
WHEN MATCHED THEN
     UPDATE SET t.email = s.email
WHEN NOT MATCHED THEN
    INSERT (t.FranchiseNo, t.Email, t.ReportID)
    VALUES  (s.FranchiseNo, s.Email, s.ReportID)
/

【讨论】:

  • 感谢您提供的示例,但是当我在 DbVisualizer 中执行上述操作时。它给了我 10:14:13 [MERGE - 0 row(s), 0.000 secs] [Error Code: 905, SQL State: 42000] ORA-00905: missing keyword ... 1 statement(s) executed, 0 row( s) 受影响,执行/获取时间:0.000/0.000 秒 [0 成功,0 警告,1 错误] 我认为该语句是正确的。你知道为什么缺少关键字会出错吗?
  • Jack - 这是一个语法错误:它不匹配而不是 UMATCHED。适合我不创建表来测试代码。道歉。
  • APC,你如何在 ID 之外的其他条件下进行测试? ID 是电子邮件表 ID,但我还想测试与另一个名为 Reports 的表相关联的 ReportID。更新工作完美无缺,但如果 ID 为空,则创建记录的未匹配子句似乎不起作用。我在 Oracle Apex 中使用这个 sql 块来更新或插入记录。
  • 感谢您提供示例,不知道这是 9i 功能。
  • APC,没关系。我想通了。如果没有Email ID,我会传入0作为ID。
【解决方案2】:

在 pl/sql 块中,您可以这样做:

更新表集列=.... 哪里.....;

如果 SQL%ROWCOUNT = 0 那么 插入...... 如果结束;

K

【讨论】:

  • 您好,感谢您的帮助。我不认为我理解 SQL%ROWCOUNT=0 部分。你能给我一个简单的例子吗?请原谅一个sql新手。
  • @Jack:SQL%ROWCOUNT 指示有多少行受到前一条语句的影响。此示例中的前一个语句是更新语句。这里的逻辑是,如果零记录受到记录更新的影响,那么记录本身一定不存在。在这种情况下,插入记录是安全的。
【解决方案3】:

使用 MERGE 命令(也被某些人称为 upsert)。 Oracle 的参考资料(附示例)here

【讨论】:

    【解决方案4】:

    附带说明,如果您是 Oracle 的新手,值得花时间了解官方的 documentation。虽然从哪里开始可能看起来很困难,但 Tom Kyte 的Road Map 是获取必读清单的好地方。

    祝你好运!

    【讨论】:

      【解决方案5】:

      我通常使用以下概念,我认为它比合并更具可读性::

      BEGIN
      
        UPDATE FREC_EMAIL
           SET email = 'blah@foo.com'
         WHERE FranchiseNo = '208254846' 
           AND ReportID = 1 
           AND ID = 165;
      
        IF SQL%NOTFOUND THEN
          INSERT INTO FREC_EMAIL
                (FranchiseNo, Email, ReportID, ID)
            VALUES
                ('208254846', 'blah@foo.com', 1, 165);
        END IF;
      
      END;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-19
        相关资源
        最近更新 更多