Postgresql

區分大小寫不一致

  • August 27, 2021

我正在嘗試學習和理解排序規則以及 postgresql 如何比較和排序字元串,但我發現不協調,我不知道我錯過了什麼。

查詢:

SELECT datname, datcollate FROM pg_database;

返回我的所有數據庫都使用 en_GB.UTF-8 排序規則。

和查詢:

SELECT table_schema, 
  table_name, 
  column_name,
  collation_name
FROM information_schema.columns
WHERE collation_name is not null
ORDER BY table_schema,
    table_name,
    ordinal_position;

返回所有列都有“C”排序規則,這意味著(根據我的研究)沒有指定排序規則。所以,我假設使用了數據庫排序規則,不是嗎?

編輯:我的錯誤在這裡。前面的查詢不會返回所有列的結果,只返回不為collation_name空的列,具有空排序規則的列是繼承數據庫排序規則的列。所以我認為 foo.bar 列有C排序規則,但null實際上是。

好吧,當我執行查詢時出現了不一致:

SELECT "name" FROM foo.bar ORDER BY "name" ASC;

其中“名稱”列數據類型是文本,而 foo.bar 是使用者創建的 schema.table 組合。結果它就像人類一樣按字母順序排列。從 a/A 到 Z/z,不管是大寫還是小寫。

但是,如果我執行以下查詢:

SELECT "table_name"
FROM information_schema.tables
WHERE
   "table_name" ~ 'some_pattern'
   AND table_schema = 'foo'
   AND table_type = 'BASE TABLE'
ORDER BY "table_name" ASC;

它以類似機器的方式對結果進行排序,逐字節比較,因此在小寫之前排序大寫。

為什麼會有這種差異?我已經看到“table_name”列數據類型不是“文本”而是“名稱”,但我找不到它是否有事可做。

將數據庫排序規則設置為 en_GB.UTF-8 不足以以人類的方式比較文本?

謝謝你的時間。

PostgreSQL 中的排序規則是這樣確定的(簡化,詳細見文件):

  • 如果存在顯式COLLATE子句,則確定排序規則
  • 否則,如果使用某種排序規則定義表列,則使用該排序規則
  • 如果該列未使用排序規則定義(它具有“預設排序規則”),則使用數據庫排序規則。

現在該列bar.name未使用排序規則定義,因此en_GB.UTF-8使用。

但是information_schema.columns有 type 的列information_schema.sql_identifier,它是數據類型的域name,它總是使用C排序規則。因此,在該查詢中,大寫字母排在小寫字母之前。

要改變這一點,您應該明確指定排序規則:

ORDER BY table_schema COLLATE "en_GB.UTF-8",
        table_name COLLATE "en_GB.UTF-8",
        ordinal_position;

引用自:https://dba.stackexchange.com/questions/298651