在SQLite中我想要不区分大小写的"SELECT LIKE name"
适用于普通的拉丁语名称,但是当名称是UTF-8且非拉丁字符时,select会变得区分大小写,如何使它也像拉丁字符一样不区分大小写?
P.S。我的sqlite是v3,我用PHP PDO连接
答案 0 :(得分:5)
对于SQLite,您有两个选择:
$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()
。
编辑:此外,这可能很有趣:
答案 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。
我还编写了另一个版本x
和basic y
和SELECT 'Á' LIKE 'à%';
值,以便重音字符与其不重音的对象匹配,例如:{ {1}}。
您可以extended romanization密切关注不定期的更新。