带有选择语句的BOUNDFILLER

时间:2019-03-02 19:01:27

标签: oracle sql-loader controlfile

我可以在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)"

2 个答案:

答案 0 :(得分:2)

  

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

不能。 (尽管文档中的措辞暗示您应该能够;我认为那是一个文档错误,应该说更多类似“无法将填充程序字段指定为另一个字段规范的SQL字符串的一部分,因为...”-然后BOUNDFILELR的例外更有意义)。

如果EMPID不是数据文件中的字段,则不需要填充。如果它在文件中但不在目标表中,则可以用普通的FILLER跳过它,除非以后也要引用该文件值。如果它是目标表中的一列,则可以使用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并具有独立的{{1 }}条目,以明确它们是不相关的。)


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

EXPRESSION

那样会抛出

  

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

两者的原因是相同的。 From the documentation

  

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

它从文件中查看字段的值,而不是在经过任何形式的SQL表达式转换之后。如果您仅使用REFNBR BOUNDFILLER, EMPID EXPRESSION "(SELECT EMPID FROM lookuptable WHERE REFNBR = :REFNBR)", EMPFIRSTNAME EXPRESSION "(SELECT FIRST_NAME FROM anothertable WHERE empid= :EMPID)", ... 进行查找,那么您可能会考虑不直接引用它并这样做:

REFNBR

,但是在EMPID "(SELECT EMPID FROM lookuptable WHERE REFNBR = :EMPID)", EMPFIRSTNAME EXPRESSION "(SELECT FIRST_NAME FROM anothertable WHERE empid= :EMPID)", ... 评估中,它仍然使用文件中值的原始值-即实际上是EXPRESSION-而不是将作为REFBNR插入的最终值。因此找不到匹配项,也不会匹配您想要的行,这可能更糟。

鉴于此,EMPID不允许使用SQL表达式-永远不会使用该表达式的结果。


还有其他一些想法...显然,重复子查询/联接很麻烦,因此我可以看到为什么在这种情况下可重用的修改值会很有用。但是由于您无法执行此操作,因此将原始BOUNDFILLER(以及文件中需要的其他任何字段)加载到暂存表(如@Littlefoot建议的物理表或外部表)中会更简单,并且然后查询并联接到其他表,以最终插入目标表。

看起来-从可能是一个非常人为的示例-就像您正在复制数据,这可能并不明智;最好在目标表中只包含REFNBR或至少只有REFNBR而不使用引用约束,因此在查询EMPID时所做的任何更改都会自动反映出来。这可能是归档和删除等较大过程的一部分。但是,使用临时表/外部表并驱使整个过程变得更简单,而不是尝试使SQL * Loader来完成某些工作,将会更加简单。

答案 1 :(得分:1)

另一种选择是切换到外部表(在后台,它使用SQL * Loader)。由于它表现为“普通”表,因此可以针对它编写(PL /)SQL。它包括联接,子查询等,因此您可以使用该查找表