131*_*131 12 postgresql version plpgsql version-sort
有没有办法在postgres中比较软件版本(例如XYZ> ABC)?我正在搜索string/varchar或"version"类型的函数.
我发现了http://pgxn.org/dist/semver/doc/semver.html,但我正在寻找替代方案(不是那么容易部署..)
非常感谢.
Erw*_*ter 23
使用更便宜string_to_array().这里不需要昂贵的正则表达式:
SELECT string_to_array(v1, '.')::int[] AS v1
, string_to_array(v2, '.')::int[] AS v2
,(string_to_array(v1, '.')::int[] > string_to_array(v2, '.')::int[]) AS cmp
FROM versions;
Run Code Online (Sandbox Code Playgroud)
您可以将版本拆分为数组,然后进行数组比较.
select regexp_split_to_array(v1, '\.')::int[] v1,
regexp_split_to_array(v2, '\.')::int[] v2,
regexp_split_to_array(v1, '\.')::int[] > regexp_split_to_array(v2, '\.')::int[] cmp
from versions;
Run Code Online (Sandbox Code Playgroud)
小智 5
正如已经建议的,一种简单的方法是使用版本的数字格式。变量“server_version_num”包含版本的数字格式。
例如。
版本 10.5 => 100500
选择当前设置('服务器版本号')
返回一个可以轻松与另一个版本号进行比较的数字。
进一步Erwin的回答,我们可以创建一个函数来将软件版本与需求进行比较(就像在ruby中一样)。我已经编写了一个函数来执行此操作,请使用它:
\nSELECT semver_match(\'4.2.0\', \'>= 4.0\'); -- TRUE\nRun Code Online (Sandbox Code Playgroud)\n这是代码和测试:
\nCREATE OR REPLACE FUNCTION semver_match(version text, req text) RETURNS boolean\n LANGUAGE SQL\n IMMUTABLE\n RETURNS NULL ON NULL INPUT\n AS $$ \n SELECT CASE\n WHEN req LIKE \'~>%\' THEN\n string_to_array(version, \'.\')::int[] >= string_to_array(substring(req from 4), \'.\')::int[]\n AND\n string_to_array(version, \'.\')::int[] <\n -- increment last item by one. (X.Y.Z => X.Y.(Z+1))\n array_append(\n (string_to_array(substring(req from 4), \'.\')::int[])[1:(array_length(string_to_array(req, \'.\'), 1) - 1)], -- X.Y\n (string_to_array(substring(req from 4), \'.\')::int[])[array_length(string_to_array(req, \'.\'), 1)] + 1 -- Z + 1\n )\n WHEN req LIKE \'>=%\' THEN string_to_array(version, \'.\')::int[] >= string_to_array(substring(req from 4), \'.\')::int[]\n WHEN req LIKE \'<=%\' THEN string_to_array(version, \'.\')::int[] <= string_to_array(substring(req from 4), \'.\')::int[]\n WHEN req LIKE \'>%\' THEN string_to_array(version, \'.\')::int[] > string_to_array(substring(req from 3), \'.\')::int[]\n WHEN req LIKE \'<%\' THEN string_to_array(version, \'.\')::int[] < string_to_array(substring(req from 3), \'.\')::int[]\n WHEN req LIKE \'=%\' THEN \n (string_to_array(version, \'.\')::int[])[1:array_length(string_to_array(substring(req from 3), \'.\'), 1)] = \n string_to_array(substring(req from 3), \'.\')::int[]\n ELSE NULL\n END $$;\n\n-- tests.\nSELECT \n ver,\n req,\n CASE WHEN semver_match(ver, req) = expected\n THEN \'\xe2\x9c\x85\' ELSE \'\xe2\x9d\x8c\' END AS test_passed\nFROM (VALUES\n (\'2.3\', \'>= 2.3\', TRUE),\n (\'2.3.1\', \'> 2.3\', TRUE),\n (\'2.3.1\', \'< 2.3.2\', TRUE),\n (\'2.3.1\', \'~> 2.3.2\', FALSE),\n (\'2.4.3\', \'~> 2.3.2\', FALSE),\n (\'2.3.2\', \'~> 2.3.2\', TRUE),\n (\'2.3.2\', \'= 2.3.2\', TRUE),\n (\'2.3.2\', \'= 2.3\', TRUE),\n (\'2.3.2\', \'= 2.4\', FALSE)\n) AS _ (ver, req, expected)\nRun Code Online (Sandbox Code Playgroud)\n有关更多实现细节,请参阅我关于该主题的博文。
\n