我正在尝试调试我自己没有制作的功能(
dms2dd).我制作了自己的测试功能(见下文)并将我的问题归结为特定的行/值.
如果我运行以下查询:
SELECT "Lat","Long",test_dolf("Lat"),test_dolf("Long") FROM pawikan WHERE "Lat" IS NOT NULL AND "Long" IS NOT NULL ORDER BY index LIMIT 1 OFFSET 29130
我得到以下输出:
'N6° 6' 9.4824"';'E118° 26' 49.1172'' ';'9.4824';'49.1172'
这正是我所期待的.
但是使用以下查询:
SELECT "Lat",CAST(test_dolf("Lat") as numeric),test_dolf("Long") FROM pawikan WHERE "Lat" IS NOT NULL AND "Long" IS NOT NULL ORDER BY index LIMIT 1 OFFSET 29130
我收到了错误
ERROR: invalid input Syntax for type numeric: "" sql state: 22P02
该错误表明我尝试转换为数字的varchar值为空,但正如您从上一个查询中看到的那样,它不是.它只是一个有效的数字varchar.实际上,如果我复制粘贴值并运行:
SELECT CAST('9.4824' AS numeric);
它完全有效,查询实际上会生成一个有效的数字.
更重要的是,如果我将第一个查询的结果存储在中间表中:
SELECT "Lat",test_dolf("Lat") as lat_sec,test_dolf("Long") as long_sec INTO dms2dd_test FROM pawikan WHERE "Lat" IS NOT NULL AND "Long" IS NOT NULL ORDER BY index LIMIT 11 OFFSET 29120
然后发出一个
SELECT CAST(long_sec as numeric),CAST(lat_sec AS numeric) FROM dms2dd_test;
它完全有效.
即使这样也可以:
SELECT test_dolf(E'N6° 6\' 9.4824"')::numeric as lat_sec
那么这里出了什么问题?它看起来像我转换为数字的第二个查询,一个不同的值传递给我的函数,但我测试了排序列(索引),它只包含唯一的bigints.
CREATE OR REPLACE FUNCTION public.test_dolf(strdegminsec character varying) RETURNS varchar AS $BODY$ DECLARE i numeric; intDmsLen numeric; -- Length of original string strCompasspoint Char(1); strnorm varchar(16) = ''; -- Will contain normalized string strDegMinSecB varchar(100); blnGotSeparator integer; -- Keeps track of separator sequences arrDegMinSec varchar[]; -- TYPE stringarray is table of varchar(2048) ; strChr Char(1); BEGIN strDegMinSec := regexp_replace(replace(strdegminsec,E'\'\'','"'),' "([0-9]+)',E' \\1"'); -- Remove leading and trailing spaces strDegMinSecB := REPLACE(strDegMinSec,' ',''); intDmsLen := Length(strDegMinSecB); blnGotSeparator := 0; -- Not in separator sequence right Now -- Loop over string,replacing anything that is not a digit or a -- decimal separator with -- a single blank FOR i in 1..intDmsLen LOOP -- Get current character strChr := SubStr(strDegMinSecB,i,1); -- either add character to normalized string or replace -- separator sequence with single blank If strpos('0123456789,.',strChr) > 0 Then -- add character but replace comma with point If (strChr <> ',') Then strnorm := strnorm || strChr; Else strnorm := strnorm || '.'; End If; blnGotSeparator := 0; ElsIf strpos('neswnesW',strChr) > 0 Then -- Extract Compass Point if present strCompasspoint := strChr; Else -- ensure only one separator is replaced with a blank - -- suppress the rest If blnGotSeparator = 0 Then strnorm := strnorm || ' '; blnGotSeparator := 0; End If; End If; End Loop; -- Split normalized string into array of max 3 components arrDegMinSec := string_to_array(strnorm,' '); return arrDegMinSec[3]; End $BODY$ LANGUAGE plpgsql IMMUTABLE COST 100;
解决方法
您得到的错误如下:
ERROR: invalid input Syntax for type numeric: ""
因此,它试图将空字符串转换为数字值.使用NULLIF功能解决这个问题怎么样?
SELECT "Lat",CAST(NULLIF(test_dolf("Lat"),'') as numeric),test_dolf("Long") FROM pawikan WHERE "Lat" IS NOT NULL AND "Long" IS NOT NULL ORDER BY index LIMIT 1 OFFSET 29130;
此外,您可能希望查看执行计划以了解此问题.可能发生的是LIMIT和OFFSET刚刚在施法后执行.这解释了为什么你没有看到空字符串的行.
编辑
糟糕,我应该在发布之前阅读你的答案.无论如何,您仍然可以使用NULLIF来解决您的问题.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。