带有 select 语句的 BOUNDFILLER

BOUNDFILLER with select statement

在 Oracle 控制文件中,我可以通过查找填充 BOUNDFILLER table吗?

例如:

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

我试过了,但我收到一条错误消息,我想是因为这是不可能的?

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

关于如何通过查找填充 BOUNDFILLER 的任何想法 table?

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

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

谢谢。

这里还有几行代码来可视化我正在尝试做的事情:

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)"

另一种方法是切换到外部 table(在幕后,它使用 SQL*Loader)。由于它的行为类似于 "ordinary" table,您可以针对它编写 (PL/)SQL。它包括联接、子查询等,因此您可以使用该 查找 table

Any ideas of how I can populate a BOUNDFILLER from a lookup table?

你不能。 (尽管文档中的措辞暗示你应该能够做到;我认为这是一个文档错误,它应该说得更像 "Filler fields cannot be specified as part of another field specification's SQL string, because..." - 然后 BOUNDFILELR 的例外更有意义)。

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

如果您想在控制文件中其他列的其他 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: Invalid bind variable EMPID in SQL string for column EMPFIRSTNAME.

两者的原因是一样的。 From the documentation:

For each input record read, the value of the field referenced by the bind variable will be substituted for the bind variable.

它从文件 中查看字段 的值,而不是在任何转换后形成 SQL 表达式。如果您只使用 REFNBR 进行该查找,那么您可能会考虑不直接引用它并执行以下操作:

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

但在 EXPRESSION 评估中它仍然使用文件中值的原始值 - 即实际上是 REFBNR - 而不是将作为 [=15= 插入的最终值].所以找不到匹配项,或者与您想要的行不匹配,这可能更糟。

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


其他一些想法...显然重复 subquery/join 很麻烦,所以我可以理解为什么可重用的修改值在这种情况下会有用。但是由于您不能这样做,因此将原始 REFNBR(以及您需要的文件中的任何其他字段)加载到暂存 table 中会更简单 - 物理或外部 table 正如@Littlefoot 建议的那样 - 然后查询并加入其他 tables 以最终插入到您的目标 table.

从一个可能非常人为的例子来看,它看起来像是在复制数据,这可能不明智;实际上,在你的目标 table 中只包含 REFNBR 或至少只包含 EMPID 可能会更好,而不是使用引用约束,因此在 anothertable 中所做的任何更改都会在 anothertable 中自动反映出来查询。这可能是归档和删除等更大过程的一部分;但是使用 staging/external table 并推动整个过程仍然会更简单,而不是试图让 SQL*Loader 做一些工作。