代码之家  ›  专栏  ›  技术社区  ›  Timo Huovinen

不区分大小写的utf8选择

  •  4
  • Timo Huovinen  · 技术社区  · 14 年前

    在SQLite中,我希望不区分大小写 "SELECT LIKE name" 对于普通的拉丁名称来说很好,但是如果名称是UTF-8格式,并且有非拉丁字符,那么select就变得区分大小写,如何使它也像拉丁字符一样区分大小写?

    p.s.我的sqlite是v3,我用PHP PDO连接

    3 回复  |  直到 14 年前
        1
  •  5
  •   amartynov    11 年前

    对于SQLite,有两个选项:

    1. 在ICU支持下编译: How to compile , Compilation options
    2. 重写LIKE函数,这里有一个完整的解决方案(从 http://blog.amartynov.ru/?p=675 )
    $pdo = new PDO("sqlite::memory:");
    
    # BEGIN
    
    function lexa_ci_utf8_like($mask, $value) {
        $mask = str_replace(
            array("%", "_"),
            array(".*?", "."),
            preg_quote($mask, "/")
        );
        $mask = "/^$mask$/ui";
        return preg_match($mask, $value);
    }
    
    $pdo->sqliteCreateFunction('like', "lexa_ci_utf8_like", 2);
    
    # END
    
    $pdo->exec("create table t1 (x)");
    $pdo->exec("insert into t1 (x) values ('[Привет España Dvořák]')");
    
    header("Content-Type: text/plain; charset=utf8");
    $q = $pdo->query("select x from t1 where x like '[_РИ%Ñ%ŘÁ_]'");
    print $q->fetchColumn();
    
        2
  •  2
  •   Community CDub    8 年前

    使用 no-case collation ,例如: LIKE name COLLATE NOCASE

    如果需要将不属于ASCII的特定字符与大小写折叠进行比较,则 NOCASE 将不起作用,因为SQLite不支持这种折叠-您必须使用您选择的Unicode库提供自己的排序规则函数,并且 sqlite3_create_collation() .

    编辑 :另外,这可能很有趣:

    How to sort text in sqlite3 with specified locale?

        3
  •  1
  •   Alix Axel    11 年前

    改进版的 LIKE 通过自定义项重载:

    $db->sqliteCreateFunction('like',
        function ($pattern, $data, $escape = null) use ($db)
        {
            static $modifiers = null;
    
            if (isset($modifiers) !== true)
            {
                $modifiers = ((strncmp($db->query('PRAGMA case_sensitive_like;')->fetchColumn(), '1', 1) === 0) ? '' : 'i') . 'suS';
            }
    
            if (isset($data) === true)
            {
                if (strpbrk($pattern = preg_quote($pattern, '~'), '%_') !== false)
                {
                    $regex = array
                    (
                        '~%+~S' => '.*',
                        '~_~S' => '.',
                    );
    
                    if (strlen($escape = preg_quote($escape, '~')) > 0)
                    {
                        $regex = array
                        (
                            '~(?<!' . $escape . ')%+~S' => '.*',
                            '~(?<!' . $escape . ')_~S' => '.',
                            '~(?:' . preg_quote($escape, '~') . ')([%_])~S' => '$1',
                        );
                    }
    
                    $pattern = preg_replace(array_keys($regex), $regex, $pattern);
                }
    
                return (preg_match(sprintf('~^%s$~%s', $pattern, $modifiers), $data) > 0);
            }
    
            return false;
        }
    );
    

    尊重 case_sensitive_like PRAGMA 正确处理 x LIKE y ESCAPE z syntax .

    我还写了另一个版本 basic extended romanization 属于 x y 值,以便重音字符与非重音字符匹配,例如: SELECT 'Á' LIKE 'à%'; .

    你可以 star the gist 以随时了解最新情况。