2010-11-26 49 views
4

在SQLite中,我想区分大小写"SELECT LIKE name" 对正常的拉丁名称可以正常工作,但是当名称使用非拉丁字符的UTF-8时,select将区分大小写,如何使其生效也像拉丁字符一样不区分大小写?不区分大小写utf8 select

p.s.我的SQLite是v3和我用PHP PDO

回答

5

SQLite的你有2种选择:

  1. 与ICU支持编译:How to compileCompilation 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

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

如果你需要非ASCII的部分与外壳折叠进行比较特定的字符,该NOCASE将无法​​正常工作,因为SQLite不支持这样的折叠 - 您将不得不使用您选择的Unicode库和sqlite3_create_collation()来提供自己的排序规则功能。

编辑:同样,这可能是有趣:

How to sort text in sqlite3 with specified locale?

+0

根据NOCASE的文档,它只是ASCII;它明确表示它不包括UTF-8。 – borrible 2010-11-26 12:56:58

+0

文档说的是,不属于ASCII **的UTF-8字符**将区分大小写。所以A = a但是Œ!=œ。编辑澄清。 – 2010-11-26 13:04:54

1

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 syntax

我还写了另外一个版本,做basicxyextended romanization,使重音字符将匹配它的重音对应,例如:SELECT 'Á' LIKE 'à%';

你可以star the gist来关注偶尔的更新。