Estou tentando aprender e entender agrupamentos e como o postgresql compara e ordena strings, mas estou encontrando uma incongruência e não sei o que estou perdendo.
A pergunta:
SELECT datname, datcollate FROM pg_database;
Retorna que todo meu banco de dados usa agrupamento en_GB.UTF-8.
E a consulta:
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;
Retorna que todas as colunas têm agrupamento 'C', o que significa (de acordo com minha pesquisa) que nenhum agrupamento é especificado. Então, suponho que o agrupamento de banco de dados seja usado, não é?
EDIT: Meu erro está aqui. A consulta anterior não retorna um resultado para todas as colunas, apenas para aquelas que collation_name
não são nulas, e as colunas com ordenação nula são as que herdam a ordenação de banco de dados. Então, eu estava pensando que as colunas foo.bar tinham C
agrupamento, mas null
na verdade eram.
Bem, a incongruência vem quando executo a consulta:
SELECT "name" FROM foo.bar ORDER BY "name" ASC;
Onde o tipo de dados da coluna "name" é texto e foo.bar é uma combinação schema.table criada pelo usuário. O resultado é semelhante ao humano ordenado alfabeticamente. De a/A a Z/z, não importa se é maiúscula ou minúscula.
Mas se eu executar a seguinte consulta:
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;
Ele ordena o resultado de maneira semelhante a uma máquina, comparando byte a byte e, portanto, ordenando maiúsculas antes de minúsculas.
Por que existe essa diferença? Eu vi que o tipo de dados da coluna "table_name" não é "texto", mas "nome", mas não consigo descobrir se tem algo a ver.
Ter o agrupamento de banco de dados definido como en_GB.UTF-8 não deve ser suficiente para comparar o texto de maneira humana?
Obrigado pelo seu tempo.
O agrupamento no PostgreSQL é determinado da seguinte forma (simplificado, para detalhes veja a documentação ):
se houver uma
COLLATE
cláusula explícita, que determina o agrupamentocaso contrário, se uma coluna da tabela foi definida com um determinado agrupamento, esse agrupamento é usado
se a coluna não for definida com uma ordenação (ela tem a “ordenação padrão”), a ordenação do banco de dados é usada.
Agora a coluna
bar.name
não foi definida com um agrupamento, entãoen_GB.UTF-8
é usada.Mas
information_schema.columns
tem colunas do tipoinformation_schema.sql_identifier
, que é um domínio sobre o tipo de dadosname
, que sempre usa oC
agrupamento. Portanto, as letras maiúsculas são classificadas antes das letras minúsculas nessa consulta.Para mudar isso, você deve especificar explicitamente o agrupamento: