通过Windows CompareStringA进行PostgreSQL排序
我有一个Delphi 6程序(单字节字符),它通过默认的不区分大小写的AnsiCompareText函数对TStringList中的字符串进行排序,该函数反过来调用Windows kernel32.dll中的CompareStringA函数。(区域设置为匈牙利语。) 我想在PostgreSQL数据库中,在Kubuntu(linux-image-3.2.0-65-generic-pae,32位x86,KDE 4.8.5)系统上进行同样的排序。它是由通过Windows CompareStringA进行PostgreSQL排序,sql,postgresql,delphi,sorting,collation,Sql,Postgresql,Delphi,Sorting,Collation,我有一个Delphi 6程序(单字节字符),它通过默认的不区分大小写的AnsiCompareText函数对TStringList中的字符串进行排序,该函数反过来调用Windows kernel32.dll中的CompareStringA函数。(区域设置为匈牙利语。) 我想在PostgreSQL数据库中,在Kubuntu(linux-image-3.2.0-65-generic-pae,32位x86,KDE 4.8.5)系统上进行同样的排序。它是由 CREATE DATABASE <..
CREATE DATABASE <...>
WITH OWNER = postgres
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'hu_HU.UTF-8'
LC_CTYPE = 'hu_HU.UTF-8'
CONNECTION LIMIT = -1;
创建数据库
拥有者=博士后
编码='UTF8'
表空间=pg_默认值
LC_-COLLATE='hu_-hu.UTF-8'
LC_CTYPE='hu_hu.UTF-8'
连接极限=-1;
如果我按C或POSIX排序,重音字符不会按字母顺序排序。
如果按默认排序规则排序,则忽略空格和一些特殊字符。当这些发生在字符串的开头时,这是一个问题。
(指定排序规则很容易,因为PostgreSQL 9.1:请参阅。)
在本主题中提出了几个问题,例如:。
答案无法概括:它只排除了第一个字符位置的“@”
我的问题也许是重复的
这里的答案指向PostgreSQL的待办事项列表:
从那以后有什么变化吗
我想要的是一个排序规则,它将空格和特殊字符保持在ASCII位置,并按字母顺序对重音字符进行排序,就像在Windows中一样
我是否必须编写自定义区域设置(如何编写)?或者是一个定制的比较函数,可能是用Delphi编写的(如何添加到PostgreSQL)?或者将特殊字符翻译成十六进制,例如,但它们将被排序到文本中。将所有字符转换为十六进制(并将大小写和重音差异映射到同一代码)似乎很糟糕——这意味着我自己编写完整的排序规则。我相信应该有解决方案。除非您可以更改数据库的编码/排序规则以匹配Windows系统,否则我认为添加一些自定义比较代码可能是您唯一的选择
如果ICU的排序顺序(如链接中所述)是您所追求的,那么请查看(Postgres ICU包装)。安装了此功能后,只需将
orderbyfoo
替换为orderbycollkey(foo,'hu\u-hu')
(同样地,对于任何显式的
/,我在这里给出了我的解决方案,尽管它不是问题的答案,因为它不使用任何排序,结果与Delphi的排序不同,它是一个PHP代码,而不是PostgreSQL。然而,这个想法可能有助于其他人将它移植到PostgreSQL或任何其他语言
include 'portable-utf8.php';
$cCharTab = array(
124 => '00', // | (field separator)
32 => '01', // space
43 => '11', // +
45 => '12', // -
47 => '14', // /
92 => '15', // \
61 => '17', // =
9658 => '19', // ►
34 => '22', // "
39 => '27', // '
40 => '28', // (
41 => '29', // )
42 => '2A', // *
46 => '2E', // .
48 => '30', // 0
49 => '31', // 1
50 => '32', // 2
51 => '33', // 3
52 => '34', // 4
53 => '35', // 5
54 => '36', // 6
55 => '37', // 7
56 => '38', // 8
57 => '39', // 9
164 => '64', // ¤
44 => '71', // ,
59 => '72', // ;
247 => '73', // ÷
58 => '73', // :
33 => '74', // !
36 => '75', // $
63 => '75', // ?
95 => '95', // _
65 => 'a0', // A
66 => 'b0', // B
67 => 'c0', // C
68 => 'd0', // D
69 => 'e0', // E
70 => 'f0', // F
71 => 'g0', // G
72 => 'h0', // H
73 => 'i0', // I
74 => 'j0', // J
75 => 'k0', // K
76 => 'l0', // L
77 => 'm0', // M
78 => 'n0', // N
79 => 'o0', // O
80 => 'p0', // P
81 => 'q0', // Q
82 => 'r0', // R
83 => 's0', // S
84 => 't0', // T
85 => 'u0', // U
86 => 'v0', // V
87 => 'w0', // W
88 => 'x0', // X
89 => 'y0', // Y
90 => 'z0', // Z
97 => 'a0', // a
98 => 'b0', // b
99 => 'c0', // c
100 => 'd0', // d
101 => 'e0', // e
102 => 'f0', // f
103 => 'g0', // g
104 => 'h0', // h
105 => 'i0', // i
106 => 'j0', // j
107 => 'k0', // k
108 => 'l0', // l
109 => 'm0', // m
110 => 'n0', // n
111 => 'o0', // o
112 => 'p0', // p
113 => 'q0', // q
114 => 'r0', // r
115 => 's0', // s
116 => 't0', // t
117 => 'u0', // u
118 => 'v0', // v
119 => 'w0', // w
120 => 'x0', // x
121 => 'y0', // y
122 => 'z0', // z
193 => 'a0', // Á
196 => 'a0', // Ä
201 => 'e0', // É
205 => 'i0', // Í
211 => 'o0', // Ó
214 => 'o1', // Ö
218 => 'u0', // Ú
220 => 'u1', // Ü
225 => 'a0', // á
228 => 'a0', // ä
231 => 'c0', // ç
233 => 'e0', // é
235 => 'e0', // ë
237 => 'i0', // í
243 => 'o0', // ó
246 => 'o1', // ö
250 => 'u0', // ú
252 => 'u1', // ü
253 => 'y0', // ý
263 => 'c0', // ć
268 => 'c0', // Č
269 => 'c0', // č
281 => 'e0', // ę
322 => 'l0', // ł
324 => 'n0', // ń
336 => 'o1', // Ő
337 => 'o1', // ő
345 => 'r0', // ř
353 => 's0', // š
367 => 'u0', // ů
368 => 'u1', // Ű
369 => 'u1', // ű
380 => 'z0' // ż
);
// Sorter:
function Sorter( $a_str )
/*
Convert $a_str to a sortable string.
*/
{
$ct = $GLOBALS['cCharTab'];
$result = '';
$arr = preg_split('//u', $a_str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($arr as $c)
$result .= $ct[utf8_ord($c)];
return $result;
}
Sorter函数将要排序的值的每个字符替换为两个字符的字母数字字符串,该字符串不受任何区域设置的影响。我在表中有一个单独的列(f_Sorter),由编写表的PHP脚本中的INSERT语句填充。(我没有更新,我只需要应用程序中的一个ORDER BY。)
是这样的:
pg_query_params( $my_pg_connection, $sql, $params );
在哪里
及
(插入和更新触发器以及服务器端功能将更加优雅。)
所以
给出了所需的结果
SELECT ...
ORDER BY f1, f2, f3
用我的“整理”
我使用“|”字符作为字段分隔符。它将在任何其他字符之前排序。结果是,较短的字符串将在具有相同前缀的较长字符串之前。(这与Delphi结果相反,但我喜欢它。)
$cCharTab数组包含大约120个字符,这些字符对我很重要。例如,请随意调整列表,更改顺序或将字段分隔符更改为TAB
portable-utf8是一个非常有用的库,用于在PHP5中处理UTF-8字符串。从下载您的问题到底是什么?仅大小写不重要的排序?不,大小写不重要的排序将很容易使用lower排序(mycl)。问题是PostgreSQL忽略了(几乎?)排序时字符串中的所有标点符号。它在某些情况下可能有用,但无法禁用。其他几个类似问题:,表明它也会激怒许多开发人员。Nick Barnes的解决方案可能是正确的,但我没有花力气开发它。
$params = array( $f1, $f2, $f3, Sorter( $f1 . '|' . $f2. '|' . $f3) );
SELECT ...
ORDER BY f_sorter
SELECT ...
ORDER BY f1, f2, f3