不区分大小写的utf8选择

时间:2010-11-26 12:48:49

标签: php sqlite select utf-8 case-sensitive

在SQLite中我想要不区分大小写的"SELECT LIKE name" 适用于普通的拉丁语名称,但是当名称是UTF-8且非拉丁字符时,select会变得区分大小写,如何使它也像拉丁字符一样不区分大小写?

P.S。我的sqlite是v3,我用PHP PDO连接

3 个答案:

答案 0 :(得分:5)

对于SQLite,您有两个选择:

  1. 使用ICU支持进行编译:How to compileCompilation options
  2. 覆盖LIKE功能,这是一个完整的解决方案(来自http://blog.amartynov.ru/?p=675
  3. $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();
    

答案 1 :(得分:2)

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

如果您需要不属于ASCII的特定字符与案例折叠进行比较,NOCASE将无效,因为SQLite不支持此类折叠 - 您必须使用自己的校对功能您选择的Unicode库和sqlite3_create_collation()

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

How to sort text in sqlite3 with specified locale?

答案 2 :(得分:1)

通过UDF重载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

我还编写了另一个版本xbasic ySELECT 'Á' LIKE 'à%';值,以便重音字符与其不重音的对象匹配,例如:{ {1}}。

您可以extended romanization密切关注不定期的更新。