Нечувствительный к регистру UTF8 выберите - PullRequest
4 голосов
/ 26 ноября 2010

В SQLite я хочу, чтобы регистр не учитывался "SELECT LIKE name" работает нормально для обычных латинских имен, но когда имя в UTF-8 с нелатинскими символами, тогда выбор становится чувствительным к регистру, как сделать так, чтобы он также чувствителен к регистру, как латинские символы?

p.s. у меня sqlite v3 и я подключаюсь с PHP PDO

Ответы [ 3 ]

5 голосов
/ 07 апреля 2011

Для SQLite у вас есть 2 варианта:

  1. скомпилировать его с поддержкой ICU: Как скомпилировать , Параметры компиляции
  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 голосов
/ 26 ноября 2010

Используйте сопоставление без регистра , например: LIKE name COLLATE NOCASE

Если вам нужно сопоставить конкретные символы, которые не являются частью ASCII, со свертыванием регистра, NOCASE не будет работать, поскольку такое свертывание не поддерживается SQLite - вам придется предоставить собственную функцию сопоставления с использованием Unicode библиотека выбора и sqlite3_create_collation().

РЕДАКТИРОВАТЬ : также, это может быть интересно:

Как отсортировать текст в sqlite3 с указанным языковым стандартом?

1 голос
/ 03 ноября 2013

Улучшенная версия LIKE перегрузки через UDF:

$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 синтаксис .

Я также написал другую версию, которая поддерживает basic и расширенную латинизацию из x и y значений, так что акцентированный символ будет соответствовать его безударному аналогу, например: SELECT 'Á' LIKE 'à%';.

Вы можете отметить звездочку , чтобы следить за случайными обновлениями.

...