5

我使用的是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 中的转换不像以前那样工作?

4

1 回答 1

7

从 PostgreSQL 8.3 开始,自动转换的数量减少了。这有两个原因改变:

  1. 引入了许多新的高性能类型,而自动转换阻止了这些类型以“一流”类型可以使用的方式使用文字。缩小解析器试图猜测数据类型的情况允许用户可以插入的新类型以更自然的方式使用。

  2. 许多错误报告结果表明人们在没有意识到自动转换正在发生时意外获得了自动转换的“好处”,从而很难找到他们的应用程序编码错误。在 8.3 版本发布后,有大致相同数量的人发帖说该更改发现了他们自己代码中隐藏的错误,因为有人抱怨他们的代码现在需要在以前不需要的地方进行强制转换。

您似乎试图通过添加隐式类型转换来“解决”这个“问题”。这是一个雷区;我不推荐它。您将限制您可以安全使用的功能,并且您将没有其他人没有的古怪小错误,并且没有人可以轻松地帮助您。最好修复您的代码,不要假设这么多隐式转换。

可能让您感到困惑的一件事是,在 PostgreSQL 中,'1.2'不是字符串文字。它是一个未知类型的文字:

test=# 选择 pg_typeof('1.2');
 pg_typeof
------------
 未知
(1 行)

PostgreSQL 尽可能地推迟解析字面量的类型,这对我描述的所有新数据类型都很有效。作为最后的手段,如果到了必须解析类型并且没有其他线索的时候,它会将其视为 type text

test=# select pg_typeof(case when true then '1.2' else null end);
 pg_typeof
------------
 文本
(1 行)

test=# select pg_typeof(case when true then '1.2' else 2.3 end);
 pg_typeof
------------
 数字
(1 行)

问题 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 行)
于 2012-08-17T20:28:11.373 回答