在 Doctrine2 DQL 查询上进行排序的 CASTING 属性
Posted
技术标签:
【中文标题】在 Doctrine2 DQL 查询上进行排序的 CASTING 属性【英文标题】:CASTING attributes for Ordering on a Doctrine2 DQL Query 【发布时间】:2011-11-16 08:20:52 【问题描述】:我正在尝试获取 Doctrine2 实体,按他们的 ID 排序,这显然是一个字符串,即使它只包含数字。 所以我想做的是这样的:
SELECT entity1, cast (entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity
ORDER BY orderId
有没有办法在 Doctrine2 中做这样的事情? 或者,如果我无法更改 id 的类型(当然是由于客户要求),那么获得我的结果的最佳做法是什么?
注意:我不是在问 SQL 代码,我是在问一个 Doctrine2 解决方案,最好是在 DQL 中
【问题讨论】:
我认为您在第 13 行缺少(
。
【参考方案1】:
你应该可以add your own function来实现这个功能。
这个类看起来像这样:
namespace MyProject\Query;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
class CastAsInteger extends FunctionNode
public $stringPrimary;
public function getSql(SqlWalker $sqlWalker)
return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS integer)';
public function parse(Parser $parser)
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->stringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
你需要注册你的函数:
$config = $em->getConfiguration();
$config->addCustomNumericFunction('INT', CastAsInteger::class);
然后就可以使用了:
SELECT e, INT(e.id) AS HIDDEN orderId
FROM Namespace\Bla\MyEntity e
ORDER BY orderId
PS:通过添加HIDDEN
关键字,别名orderId
将不会出现在结果中(并且仅用于排序)。
【讨论】:
在我自己的函数中,我有一个SingleValuedPathExpression
像 u.group
并希望使用实际的 Expression 对象将其“包装”在 "CAST(" SingleValuedPathExpression " AS DECIMAL(10,2))"
中......我该怎么做? CAST ...在手工构建时会是什么样的表达?
好吧,没关系;我使用了一个自定义表达式并修改了它的->dispatch()
方法以满足我的需要。清洁如预期。教义真棒。 :)
如果目标数据库是mysql,这行不行:return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS integer)'
;试试这个:return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS SIGNED)';
只是为了在 Symfony 中记录,您将寄存器部分放在 config.yml【参考方案2】:
基于 Jasper N. Brouwer 的回答,这是一个稍微增强的解决方案:
<?php
namespace MyProject\Query;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
class Cast extends FunctionNode
/** @var \Doctrine\ORM\Query\AST\PathExpression */
protected $first;
/** @var string */
protected $second;
/**
* @param SqlWalker $sqlWalker
*
* @return string
*/
public function getSql(SqlWalker $sqlWalker)
return sprintf("CAST(%s AS %s)",
$this->first->dispatch($sqlWalker),
$this->second
);
/**
* @param Parser $parser
*
* @return void
*/
public function parse(Parser $parser)
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->first = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_AS);
$parser->match(Lexer::T_IDENTIFIER);
$this->second = $parser->getLexer()->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
现在应该可以像这样编写 DQL:
SELECT e, CAST(e.id AS integer) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId
【讨论】:
【参考方案3】:认为在这种情况下最好使用一些额外的功能(而不是试图“规避”他们的功能)。例如。为Doctrine 2
添加几乎所有必要(不支持)的东西的优秀解决方案是DoctrineExtensions by beberlei (github)。有了它,就可以直接使用CAST
-statement,就像在 OP 的情况下一样:
("Symfony-example") 例如在你的config.xml
添加行:
orm:
..
entity_managers:
....
dql:
....
string_functions:
CAST: DoctrineExtensions\Query\Mysql\Cast
然后你可以像这样使用它:
SELECT entity1, CAST(entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity
ORDER BY orderId
【讨论】:
【参考方案4】:不确定这是否有效,但要访问实体 ID,您需要 IDENTITY() DQL 函数。试试这个:
SELECT entity1 FROM Namespace\Bla\MyEntity ORDER BY IDENTITY(entity1)
【讨论】:
【参考方案5】:我昨天刚刚在自己的代码中做了类似的事情。我能够做到:
select cast(entity1 as int) as OrderID
from yourtablename
where yourconditions
我必须将我的实际转换为 money 然后 int,但如果你没有小数,你不应该有这个问题。您也可以尝试转换为数字或使用转换而不是转换,但在这种情况下转换更好。
如果 OrderID 中已经有相同的值,为什么还需要 entity1 作为列?
【讨论】:
你知道我使用的是doctrine2 DQL而不是MySQL吗? 我没有意识到这一点,我使用的是用于 sqlserver 的 sql,而不是 mysql,但它们非常相似。【参考方案6】:在不改变数据类型的情况下试试这个
select (entity1 * 1) as display_value, entity1 as return_value
from Table_Name
order by 1 asc;
【讨论】:
你知道我使用的是doctrine2 DQL而不是MySQL吗?【参考方案7】:我想你想通过entity1
订购。如果您的 entity1 数据类型是整数,则无需将其更改为整数,否则您应该这样做。下面是你的查询。试试这个。
select entity1,cast(entity1 as integer) as order_id from Table_Name order by 1 asc;
【讨论】:
如前所述,由于客户要求,我无法更改以上是关于在 Doctrine2 DQL 查询上进行排序的 CASTING 属性的主要内容,如果未能解决你的问题,请参考以下文章
doctrine2 dql,在进行类似比较时使用带有%wildcard的setParameter