Sql Oracle使用FK检查多次插入表

Sql Oracle使用FK检查多次插入表,sql,oracle10g,Sql,Oracle10g,我必须在Oracle表中插入许多产品价值记录。我从一个xls文件中获取所有数据,用PHP对其进行处理,然后(目前)抛出一条长SQL语句。在插入每个记录时,我希望对照数据库中已有的产品检查从xls获得的产品ID,如果ID与产品不匹配,则跳过插入。我尝试过的陈述如下: INSERT ALL INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) VALUES (NULL,

我必须在Oracle表中插入许多产品价值记录。我从一个xls文件中获取所有数据,用PHP对其进行处理,然后(目前)抛出一条长SQL语句。在插入每个记录时,我希望对照数据库中已有的产品检查从xls获得的产品ID,如果ID与产品不匹配,则跳过插入。我尝试过的陈述如下:

INSERT ALL 
INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR)
    VALUES (NULL, 123456, 81, 10000)
INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR)
    VALUES (NULL, 7890, 76, 11000)
SELECT * FROM DUAL;
这给了我一个机会

[Err] ORA-02291: integrity constraint (OURDB.PXG_PRODUCTO_FKEY) violated - parent key not found
错误消息。在尝试插入之前,我想检查
PXG_PRODUCTO
键是否存在。我应该对照
PRODUCTOS.PRO\u ID
字段进行检查。我试过类似的东西

INSERT ALL 
INTO PRODUCTOS_X_PLANES_CATEGORIA (PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) 
    VALUES (NULL, 123456, 81, 10000) 
    USING PRODUCTOS ON PXG_PRODUCTO = PRO_ID
INTO PRODUCTOS_X_PLANES_CATEGORIA (PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) 
    VALUES (NULL, 7890, 76, 11000) 
    USING PRODUCTOS ON PXG_PRODUCTO = PRO_ID
SELECT * FROM DUAL;
只得到一个

[Err] ORA-00928: missing SELECT keyword
信息。正确的语法是什么?或者,如果我完全错了,我应该怎么做呢

使用

INSERT ALL 
 INTO PRODUCTOS_X_PLANES_CATEGORIA (PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) VALUES (NULL, 123456, 81, 10000) WHERE EXISTS (SELECT * FROM PRODUCTOS WHERE 123456 = PRO_ID)
 INTO PRODUCTOS_X_PLANES_CATEGORIA (PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) VALUES (NULL, 7890, 76, 11000) WHERE EXISTS (SELECT * FROM PRODUCTOS WHERE 7890 = PRO_ID)
SELECT * FROM   DUAL;
仍然导致

[Err] ORA-00928: missing SELECT keyword

您可以在以下位置使用

INSERT INTO PRODUCTOS_X_PLANES_CATEGORIA 
    (PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) 
    SELECT NULL, 973082, 76, 10000
    FROM dual
    WHERE EXISTS (SELECT * FROM PRODUCTOS WHERE 973082 = PRO_ID)

经过讨论,我现在知道您正在动态构造INSERT ALL,每行插入一个INTO子句:

INSERT ALL 
INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR)
    VALUES (NULL, 123456, 81, 10000)
INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR)
    VALUES (NULL, 7890, 76, 11000)
...
etc.
...
SELECT * FROM DUAL;
您无法将EXISTS检查添加到INTO子句,因此使用此INSERT ALL语法无法解决您的问题。然而,无论如何,构造一个巨大的INSERT ALL语句并不是最好的方法。我建议您考虑将值加载到数组中,并使用FORALL执行如下大容量插入:

FORALL i IN 1..array.count
  INSERT INTO PRODUCTOS_X_PLANES_CATEGORIA(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR)
  VALUES (NULL, array(i).PXG_PRODUCTO, array(i).PXG_PLAN_CATEGORIA, array(i).PXG_VALOR);
  SAVE EXCEPTIONS;
您需要了解异常是如何处理的-请参见类似的内容

INSERT INTO PRODUCTOS_X_PLANES_CATEGORIA 
(PXG_ID, PXG_PRODUCTO, PXG_PLAN_CATEGORIA, PXG_VALOR) 
SELECT NULL AS PXG_ID, PRO_ID AS PXG_PRODUCTO, 76 PXG_PLAN_CATEGORIA, 10000 PXG_VALOR FROM PRODUCTOS WHERE PRO_ID = 973082;

我得到了
[Err]ORA-00928:缺少选择关键字suggestion@Adriano瓦罗利·皮亚扎:如果用
select
替换
,是否有效?回答中编辑。我得到一个
[Err]ORA-00923:FROM关键字未在预期的位置找到
。@Adriano Varoli Piazza:你说得对,你需要dual
中的
。添加到答案中。这并不是我想要的(一个insert语句而不是N个语句),但我将选择它作为答案,因为(a)它可以工作,(b)鉴于Oracle在这里的专业知识,维护
批量收集
解决方案将更加困难。啊,很抱歉,举个例子。这是一个大容量插入,PXG_PRODUCTO键可能引用不同的项,因此它的值并不总是相同的。好吧,那么您的SQL到底是什么样子的呢?是吗?我仍然只看到文字值的单行插入。我没有看到您的编辑。我从一个xls文件中获取所有这些数据,并且我有文字值。我的意思是,当我解释你的第一个答案时,它们并不总是相同的。在我更新表中的价格之前,我想对照数据库中已有的产品检查xls中的文字产品ID。我没有变量,每行有不同的文字。我的意思是,在一行中,我的产品ID可能是123465,在下一行中可能是78901,在第三行中可能是123,等等。所有不同的产品,正如我所想,我每次都必须检查,而不仅仅是在语句末尾检查一次。这是否适用于
全部插入
?我需要一次插入许多产品。或者这也一样有效?老实说,我不知道你到底想做什么。你能告诉我们你是如何创建原始的insert all语句的吗?不幸的是,我附近没有服务器来测试任何东西。但我不认为你可以像这样使用插入。我们的情况是,我们必须同时插入许多记录。我们没有执行多次单次插入,而是向存储过程发送了一个Oracle集合(实际上有几个集合,具体取决于要插入的字段数),并使用一个insert语句插入这些集合中的所有内容。然后,您可以在执行单个SQL时检查任何业务规则。