doulun0651 2014-03-11 12:33
浏览 48
已采纳

在Doctrine DQL查询中使用COLLATE(Symfony2)

I can't find anything related to using COLLATE in a DQL query with Doctrine (and ofcourse it doesn't seem to work).

My specific problem:

I have a table with utf8_general_ci charset. I have one specific field in it which has accented characters (like 'á', 'ű', 'ő' etc.)

A basic comparison with utf8_general_ci is not able to determine the difference between regular chars and their accented pairs (a = á, u = ű, o = ő), which is perfectly fine for me for the majority of the queries that land on that table! So if I have let's say:

 col1 |  col2
------|-------
   1  | árvíz  
------|-------
   2  | arviz

This query will return both results:

SELECT * FROM `table` WHERE `col2` = 'arviz'

Again, this is perfectly fine for me for most of the use cases!

But there is one specific funcionality, where I need to determine the difference, and in regular MySQL I could use:

SELECT * FROM `table` WHERE `col2` COLLATE utf8_bin = 'arviz'

This returns only the unaccented version.

The question is, can something like this be done using either Doctrine's createQuery (write the dql), or query builder?

I think I've read throught all the relevant documentation, but cannot find a way to do this. Is is possible somehow?

  • 写回答

1条回答 默认 最新

  • dongying3830 2014-03-11 15:15
    关注

    Following Cerad 's suggestion to write a custom DQL function: http://www.doctrine-project.org/2010/03/29/doctrine2-custom-dql-udfs.html

    I managed to create this:

    namespace MyCompany\MyBundle\DQL;
    
    use Doctrine\ORM\Query\AST\Functions\FunctionNode;
    use Doctrine\ORM\Query\Lexer;
    
    class CollateFunction extends FunctionNode
    {
        public $expressionToCollate = null;
        public $collation = null;
    
        public function parse(\Doctrine\ORM\Query\Parser $parser)
        {
            $parser->match(Lexer::T_IDENTIFIER);
            $parser->match(Lexer::T_OPEN_PARENTHESIS);
            $this->expressionToCollate = $parser->StringPrimary();
    
            $parser->match(Lexer::T_COMMA);
    
            $parser->match(Lexer::T_IDENTIFIER);
            $lexer = $parser->getLexer();
            $this->collation = $lexer->token['value'];
    
            $parser->match(Lexer::T_CLOSE_PARENTHESIS);
        }
    
        public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
        {
            return sprintf( '%s COLLATE %s', $this->expressionToCollate->dispatch($sqlWalker), $this->collation );
        }
    }
    

    When registered to the config.yml (http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html) This will look for a Collate 'function' with two arguments: a field and a charset (no valid charset detection yet).

    Works like (written in DQL)

    COLLATE( field , collation ) 
    

    And creates (in runable MySQL)

    `field` COLLATE collation 
    

    Ofcourse collation should be a valid charset (such as utf8_bin) or you will get a MySQL error.

    I guess there is a simpler solution, but I only could create this as a 'function'. At least the problem is solved.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 2024-五一综合模拟赛
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭