我使用
postgresql版本8.2.22,然后我升级到postgresql 9.1.3并且升级成功完成.
但是现在有些演员阵容不像以前一样!
在Postgres 8.2.22
我运行这两个查询,它们都正常工作:
POSTGRES8222=# select TO_NUMBER('12345678',9999999999.99); to_number ========= 12345678 (1 row) POSTGRES8222=# select a ||'$'|| b from test; ?column? ---------- 1$abcdef 2$ghijkl 3$3456 (3 rows)
升级到Postgres 9.1.3后
select TO_NUMBER('12345678',9999999999.99); ERROR: function to_number(unknown,numeric) does not exist LINE 1: select TO_NUMBER('12345678',9999999999.99); ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. EXCEPTION org.postgresql.util.PsqlException: ERROR: function to_number(numeric,numeric) does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts. Position: 150 select a ||'$'|| b from test; ERROR: operator is not unique: numeric || unknown LINE 1: select a ||'$'|| b from test; ^ HINT: Could not choose a best candidate operator. You might need to add explicit type casts. ********** Error ********** ERROR: operator is not unique: numeric || unknown sql state: 42725 Hint: Could not choose a best candidate operator. You might need to add explicit type casts. Character: 10
为什么postgresql中的转换不像以前那样工作?
解决方法
从Postgresql 8.3开始,自动演员阵容较少.这改变了两个原因:
>正在引入许多新的高性能类型,自动转换使这些类型无法以“一流”类型的方式使用文字.缩小解析器试图猜测数据类型的情况允许用户可以插入的新类型以更自然的方式使用.
>许多错误报告竟然是人们在不认识到它发生时意外地获得自动投射的“好处”,因此很难找到他们的应用程序编码错误.在8.3发布之后,大约有相同数量的人发帖说改变发现了他们自己代码中隐藏的错误,因为有人抱怨他们的代码现在需要在之前没有的代码.
看起来你试图通过添加隐式类型转换来“解决”这个“问题”.这是一个雷区;我不推荐它.你将限制你可以安全使用的功能,你将无法完成其他人没有做过的古怪小错误,没有人能轻易帮助你.最好修复代码,不要假设这么多隐式转换.
令你困惑的一件事是,在Postgresql中,’1.2’不是字符串文字.它是一个未知类型的文字:
test=# select pg_typeof('1.2'); pg_typeof ----------- unknown (1 row)
只要可能,Postgresql就不会解析文字的类型,这对我所描述的所有新数据类型都很有效.作为最后的手段,如果时间到了,它必须解决类型并且没有其他线索,它会将其视为类型文本.
test=# select pg_typeof(case when true then '1.2' else null end); pg_typeof ----------- text (1 row) test=# select pg_typeof(case when true then '1.2' else 2.3 end); pg_typeof ----------- numeric (1 row)
问题2,“aftertypecast”失败,因为你添加了所有隐式类型转换,有多个可能的运算符||可以根据它执行的隐式类型转换来选择,并且没有原则性的方法可以在它们中进行选择.如果您将该行更改为以下内容,它应该再次起作用:
select a || '$'::text || b from test;
我认为不添加那些隐式转换并更改第一个问题代码会更清晰,更安全:
select TO_NUMBER('12345678',9999999999.99);
至:
select TO_NUMBER('12345678','9999999999.99');
毕竟,第二个参数是格式字符串,而不是数字.如果您想要执行以下操作,则无法省略引用:
test=# select to_number('12,454.8-','99G999D9S'); to_number ----------- -12454.8 (1 row)