Propel:从别名连接表中选择列

时间:2013-10-22 17:30:41

标签: php mysql sql orm propel

我有以下两个表:

  table_a:
    id_table_a: { type: integer, primaryKey: true, autoIncrement: true, required: true }
    name:       { type: varchar(255) }
    id_table_b: { type: integer, foreignTable: table_b, foreignReference: id_table_b }

  table_b: 
    id_table_b: { type: integer, primaryKey: true, autoIncrement: true, required: true }
    value_1:    { type: varchar(255) }
    value_2:    { type: integer }

我想使用select方法构建SQL查询以跳过水合作用,也使用连接表上的别名:

 TableAQuery::create()
            ->useTableBQuery('a')
                // some filters methods
            ->endUse()
            ->useTableBQuery('b')
                // some filters methods
            ->endUse()
            ->select(array('a.value_1', 'b.value_2'))
            ->find();

现在问题就在于此。 Propel不断将ab别名更改为table_b生成错误的SQL,如下所示:

SELECT table_b.value_1 AS "a.value_1", table_b.value_2 AS "b.value_2" FROM `table_a`
LEFT JOIN `table_b` `a` ON (table_a.id_table_b=a.id_table_b) 
LEFT JOIN `table_b` `b` ON (table_a.id_table_b=b.id_table_b)

而不是

SELECT a.value_1 AS value_1, b.value_2 AS value_2 FROM `table_a` 
LEFT JOIN `table_b` `a` ON (table_a.id_table_b=a.id_table_b) 
LEFT JOIN `table_b` `b` ON (table_a.id_table_b=b.id_table_b)

我该如何处理?我使用Propel 1.6.9

更新

我还检查了推进1.7.1,没有区别。

2 个答案:

答案 0 :(得分:4)

在我阅读了jambmberlain关于where caluse的评论之后我做了一点研究,我得出的结论是

  • 在推进函数中键入列名时应始终使用UpperCamelCase样式,即使有时如果不使用此样式也能正常工作
  • 解决方案取决于Propel版本

可能没有Propel< = 1.6.7的解决方案(或者原始SQL查询可能是唯一的解决方案),因为无论我尝试多少,我总是以Cannot fetch ColumnMap for undefined column: ID_TABLE_B Propel异常结束。

对于Propel> = 1.6.8,这将起作用:

如果您需要带有别名列的数组

TableAQuery::create()
  ->useTableBQuery('a')
      // some filters methods
  ->endUse()
  ->useTableBQuery('b')
      // some filters methods
  ->endUse()
  ->select(array('a.Value1', 'b.Value2')) // notice a.value_1 or b.value_2 won't work
  ->find();

如果您需要使用别名列中的虚拟列对象

TableAQuery::create()
  ->useTableBQuery('a')
      // some filters methods
  ->endUse()
  ->useTableBQuery('b')
      // some filters methods
  ->endUse()
  ->withColumn('a.Value1') // notice a.value_1 won't work
  ->withColumn('b.Value2') // notice b.value_2 won't work
  ->find();

答案 1 :(得分:3)

你能改变它吗?

TableAQuery::create()
        ->useTableBQuery('a')
            // some filters methods
        ->endUse()
        ->useTableBQuery('b')
            // some filters methods
        ->endUse()
        //->select(array('a.value_1', 'b.value_2'))
        ->addAsColumn('a.value_1', 'a.value_1')
        ->addAsColumn('b.value_2', 'b.value_2')
        ->find();

警告:我不是Propel用户。 我只是想知道自动生成的useXXXQuery()是否同时在同一个关系上设置表别名,或类似的东西。

与上述查询一样,将select()替换为两个addAsColumn()语句。这有点像黑客,但我认为它可以实现你想要的结果。

我花了一些时间阅读Propel源代码,并且我得出结论,Propel 1并不是为了在你尝试的多次连接的同一个表上使用不同的别名而构建的。在ModelCriteria.php中,使用$column->getFullyQualifiedName可确保在连接表的选择中使用全名(table.column),而不管别名如何。 (见https://github.com/propelorm/Propel/blob/7ddb0956b699343d33ce0c94043fa5970cc719c1/runtime/lib/query/ModelCriteria.php#L2082。)我希望这确实是一个错误。

如果使用addAsColumn()方法而不是select(),Propel将使用您的文字SQL表达式,无论它是别名,列还是其他任何内容。也就是说,我不确定这是否是它的预期用途。