Postgres 12 不区分大小写的比较

Zil*_*oni 8 postgresql locale collation case-insensitive icu

我正在尝试将 C# 应用程序 (+EF6) 使用的 SQL Server DB 移动到 Postgres 12,但我在进行不区分大小写的字符串比较方面运气不佳。现有的 SQL Server 数据库使用 SQL_Latin1_General_CP1_CI_AS 排序规则,这意味着所有 WHERE 子句都不必担心大小写。

我知道 CIText 以前是这样做的,但现在被非确定性排序规则所取代。

我创建了这样一个排序规则;

CREATE COLLATION ci (provider = icu, locale = 'und-u-ks-level2', deterministic = false);
Run Code Online (Sandbox Code Playgroud)

并且当它以每列为基础应用于 CREATE TABLE 时,它确实有效 - 忽略大小写。

CREATE TABLE casetest (
id serial NOT NULL,
code varchar(10) null COLLATE "ci",
CONSTRAINT "PK_id" PRIMARY KEY ("id"));
Run Code Online (Sandbox Code Playgroud)

但是从我读过的内容来看,它必须应用于每个 varchar 列,并且不能在整个数据库中全局设置。

这样对吗?

由于杂乱,我不想在任何地方使用 .ToLower() 并且不会使用列上的任何索引。

我尝试修改 pg_collat​​ion 中预先存在的“默认”排序规则以匹配“ci”排序规则的设置,但没有效果。

提前致谢。PG

Lau*_*lbe 6

你做对了。ICU 排序规则不能用作数据库默认排序规则(尚),但必须在列定义中使用。

这种限制很烦人,而不是事物的本质。它可能会在未来的某个版本中取消。

您可以使用DO语句来更改所有字符串列的排序规则:

DO
$$DECLARE
   v_table  regclass;
   v_column name;
   v_type   oid;
   v_typmod integer;
BEGIN
   FOR v_table, v_column, v_type, v_typmod IN
      SELECT a.attrelid::regclass,
             a.attname,
             a.atttypid,
             a.atttypmod
      FROM pg_attribute AS a
         JOIN pg_class AS c ON a.attrelid = c.oid
      WHERE a.atttypid IN (25, 1042, 1043)
        AND c.relnamespace::regnamespace::name
            NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
   LOOP
      EXECUTE
         format('ALTER TABLE %s ALTER %I SET DATA TYPE %s COLLATE ci',
                v_table,
                v_column,
                format_type(v_type, v_typmod)
         );
   END LOOP;
END;$$;
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望查询不区分大小写,则可以使用此脚本将列类型转换为 [citext](https://www.postgresql.org/docs/current/citext.html)。这是一个[附加提供的模块](https://www.postgresql.org/docs/current/contrib.html#footer),在进行查询之前调用 lower() 。通过 `CREATE EXTENSION citext;` 导入一次,并将格式行更改为 `format('ALTER TABLE %s ALTER COLUMN %I SET DATA TYPE CITEXT'`。这样做的好处是 `LIKE、ILIKE 和 ~*` [继续工作](https://dba.stackexchange.com/questions/266097) 并通过“LIKE”语句启用可移植 SQL。 (2认同)
  • @dipold 在 v15 中,您可以使用 ICU 排序规则作为数据库排序规则,但不能使用不区分大小写的排序规则。 (2认同)