Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 11g中条件子查询的替代方案_Oracle_Plsql_Subquery - Fatal编程技术网

Oracle 11g中条件子查询的替代方案

Oracle 11g中条件子查询的替代方案,oracle,plsql,subquery,Oracle,Plsql,Subquery,我对oracle pl/sql越来越有经验,但这个问题似乎一直存在:我有一个将外部数据合并到数据库表中的过程,该过程如下所示: PROCEDURE updateTable (ts DATE, val NUMBER, id NUMBER) BEGIN IF id NOT IN (15, 16, 23) THEN MERGE INTO myTable dest USING (SELECT ts, val, id FROM Dual) src ON (src.id =

我对oracle pl/sql越来越有经验,但这个问题似乎一直存在:我有一个将外部数据合并到数据库表中的过程,该过程如下所示:

PROCEDURE updateTable (ts DATE, val NUMBER, id NUMBER)
BEGIN
  IF id NOT IN (15, 16, 23)
  THEN 
    MERGE INTO myTable dest
    USING (SELECT ts, val, id FROM Dual) src
    ON (src.id = dest.id AND src.ts = dest.ts)
    WHEN MATCHED THEN UPDATE SET dest.val = src.val
    WHEN NOT MATCHED THEN INSERT (ts, val, id) VALUES (src.ts, src.val, src.id);
  END IF;
END;
到目前为止,这一切都很好。现在的问题是,被排除的id列表是硬编码的,将另一个表中的id列表(即上面代码中的id列表)替换为行中的id列表将更加动态

IF id NOT IN (15, 16, 23)
有点像

IF id NOT IN (SELECT id FROM excluTable)
返回臭名昭著的错误:PLS_00405:在此上下文中不允许子查询 如果它只有一个id,我可以简单地创建一个变量并将id选择到其中。不幸的是,这是一个相当长的列表。我曾尝试将它们批量收集到一个数组中,但也没有找到将其放入条件子句的方法。我相信有一个优雅的解决方案。
谢谢你的帮助

排除表中可能有许多ID,但您只将一个ID传递到过程中。您可以查看表中是否存在该单个值,并将计数放入局部变量,然后检查该计数是零还是非零;比如:

PROCEDURE updateTable (ts DATE, val NUMBER, id NUMBER) IS
  l_excl_id PLS_INTEGER;
BEGIN
  SELECT count(*)
  INTO l_excl_id
  FROM excluTable
  WHERE excluTable.id = updateTable.id;

  IF l_excl_id = 0
  THEN 
    MERGE INTO myTable dest
    USING (SELECT ts, val, id FROM Dual) src
    ON (src.id = dest.id AND src.ts = dest.ts)
    WHEN MATCHED THEN UPDATE SET dest.val = src.val
    WHEN NOT MATCHED THEN INSERT (ts, val, id) VALUES (src.ts, src.val, src.id);
  END IF;
END;
顺便说一句,如果过程参数名称与表列名或其他标识符相同,则可能会引起混淆。例如,由于
id
是表中的过程参数名和列名,因此我必须在它们前面加上前缀:

  WHERE excluTable.id = updateTable.id;
一个带有表名(或别名,如果您添加了别名),另一个带有过程名。如果你这么做了

  WHERE excluTable.id = id

然后,范围规则意味着它将表中的每个ID与自身匹配,而不是与参数匹配,因此您将对所有行进行计数,并且可能无法立即看出它为何没有按照预期的方式运行。如果参数被命名为,比如,
p_ts
p_id
,那么您就不必解释这种歧义。这也是为什么我在本地标志变量前面加上了
l\ucode>

谢谢你,先生!那很快。你是对的,这些参数实际上被称为
puts
puid
等等。我刚刚偶然发现了另一种使用id数组的方法。然后
如果p_id不是idArray的成员,那么
也会执行此任务。是的,但是您选择的数据比您需要的多,并且将所有这些数据存储在内存中,存储在数组中。查找特定ID的速度应该更快(至少在索引的情况下)。