带有select语句的BOUNDFILLER

问题描述 投票:0回答:2

在Oracle Control File中,我可以从查找表中填充BOUNDFILLER吗?

例如:

EMPID BOUNDFILER "SELECT EMPID from employees where refno=refno"

我试过,但我收到错误信息,我认为因为这是不可能的?

错误消息是:期望有效的列规范,“,”或“)”,找到....

关于如何从查找表中填充BOUNDFILLER的任何想法?

编辑:显然我不清楚问题是什么。

我需要从查找表中填充BOUDFILLER。当值来自源文件时,一切正常。

谢谢。

这里有几行代码可视化我想要做的事情:

EMPID      BOUNDFILLER "(SELECT EMPID FROM table WHERE REFNO = :REFNBR)" (Trying to get empid from another table to use below)
EMPFIRSTNAME "(SELECT FIRST_NAME FROM table WHERE TRANS = :TRANS AND FILENAME =:FILENAME)"
EMPLASTNAME  "(SELECT LAST_NAME FROM table WHERE TRANS = :TRANS AND FILENAME =:FILENAME)"
EMPEMAIL    "(SELECT EMPEMAIL FROM table WHERE EMPID = :EMPID)"
EMPSUPERVISORNAME   "(SELECT EMPSUPERVISORNAME FROM table WHERE EMPID = :EMPID)"
EMPHOMECITY      "(SELECT EMPHOMEOFFICECITY FROM table WHERE EMPID = :EMPID)"
oracle sql-loader controlfile
2个回答
2
投票

关于如何从查找表中填充BOUNDFILLER的任何想法?

你不能。 (尽管文档中的措辞暗示你应该能够;我认为这是一个doc bug,它应该说更像“填充字段不能被指定为另一个字段规范的SQL字符串的一部分,因为......” - 然后BOUNDFILELR的例外更有意义)。

如果EMPID不是数据文件中的字段,那么您不需要填充它。如果它在文件中但不在目标表中,则可以使用普通的FILLER跳过它,除非您想稍后引用该文件值。如果它是目标表中的一列,那么您可以使用EXPRESSION子句来进行查找,但之后您不能将其称为其他地方的绑定变量。

如果要在控制文件中的其他SQL的其他SQL表达式中引用它,则需要将查找重复为子查询。

例如,您可以:

REFNBR BOUNDFILLER,
EMPID EXPRESSION "(SELECT EMPID FROM lookuptable WHERE REFNBR = :REFNBR)",
EMPFIRSTNAME EXPRESSION "(SELECT FIRST_NAME FROM anothertable WHERE empid = (SELECT EMPID FROM lookuptable WHERE REFNO = :REFNBR))",
...

或稍微加入:

REFNBR BOUNDFILLER,
EMPID EXPRESSION "(SELECT EMPID FROM lookuptable WHERE REFNBR = :REFNBR)",
EMPFIRSTNAME EXPRESSION "(SELECT t1.FIRST_NAME FROM lookuptable t1 JOIN anothertable t2 ON t2.empid = t1.empid WHERE t1.REFNBR = :REFNBR)",
...

假设它们在数据文件中没有相应的字段,我已经将它们声明为EXPRESSION - 主要是出于这些目的,数据文件只有REFNBR。 (你可能还有其他未显示的字段;你甚至可能有与你忽略的EMPID字段相对应的字段 - 但在这种情况下我会将它们视为FILLER并且无论如何都要有独立的EXPRESSION条目以表明它们不是有关。)


你不能做的是提供一个SQL表达式作为BOUNDFILLER的一部分,或者在另一个字段的SQL表达式中引用一个EXPRESSION,即:

REFNBR BOUNDFILLER,
EMPID EXPRESSION "(SELECT EMPID FROM lookuptable WHERE REFNBR = :REFNBR)",
EMPFIRSTNAME EXPRESSION "(SELECT FIRST_NAME FROM anothertable WHERE empid= :EMPID)",
...

因为那会抛出

SQL * Loader-291:EMPFIRSTNAME列的SQL字符串中的无效绑定变量EMPID。

两个原因都是一样的。 From the documentation

对于读取的每个输入记录,绑定变量引用的字段的值将替换绑定变量。

它从文件中查看字段的值,而不是在从SQL表达式进行任何转换之后。如果你只是使用REFNBR进行查找,那么你可能会考虑不直接参考和执行:

EMPID "(SELECT EMPID FROM lookuptable WHERE REFNBR = :EMPID)",
EMPFIRSTNAME EXPRESSION "(SELECT FIRST_NAME FROM anothertable WHERE empid= :EMPID)",
...

但在EXPRESSION评估中,它仍然使用文件中值的原始值 - 即实际上是REFBNR - 而不是将作为EMPID插入的最终值。因此,找不到匹配项,或者与您预期的行不匹配,这可能更糟。

鉴于此,BOUNDFILLER允许使用SQL表达式是没有意义的 - 该表达式的结果永远不会被使用。


其他一些想法......显然重复子查询/连接是混乱的,所以我可以看到为什么可重用的修改值在这种情况下会有用。但是既然你不能这样做,那么将原始的REFNBR(以及你需要的任何其他字段)加载到一个临时表 - 或者像@Littlefoot建议的物理表或外部表 - 然后查询和连接到其他表以在目标表中进行最终插入。

它看起来 - 从可能是一个非常人为的例子 - 就像你复制数据,这可能是不明智的;实际上只需要在目标表中使用REFNBR或至少只是EMPID而不是参考约束,所以在anothertable中进行的任何更改都会在查询时自动反映出来。这可能是存档和删除的更大过程的一部分,或者某些东西;但是,使用登台/外部表并驱动整个过程仍然更简单,而不是试图让SQL * Loader做一些工作。


1
投票

另一种方法是切换到外部表(在场景后面,它使用SQL * Loader)。因为它表现为“普通”表,所以可以针对它编写(PL /)SQL。它包括连接,子查询等,因此您可以使用该查找表。

© www.soinside.com 2019 - 2024. All rights reserved.