Das Ausführen von Typ-Cast-functionen in PostgreSQL 9.1.3 ist nicht dasselbe wie in PostgreSQL 8.2.22. Die Verkettung funktioniert nicht korrekt

Ich habe postgresql Version 8.2.22 verwendet, dann habe ich auf postgresql 9.1.3 aktualisiert und das Upgrade wurde erfolgreich abgeschlossen.

Aber jetzt funktionieren einige Abgüsse nicht mehr wie zuvor!

In Postgres 8.2.22

Ich führe diese zwei Abfragen aus und beide funktionieren korrekt:

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) 

Nach dem Upgrade auf Postgres 9.1.3

Ich führe die gleichen Abfragen und jetzt casting sie Fehler:

 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 

Warum funktioniert casting in postgresql nicht so wie vorher?

Ab PostgreSQL 8.3 gibt es weniger automatische Umwandlungen. Dies wurde aus zwei Gründen geändert:

  1. Viele neue leistungsstarke Typen wurden eingeführt, und das automatische Casting verhinderte, dass diese Literale so verwenden konnten, wie es "erstklassige" Typen könnten. Durch die Eingrenzung der Fälle, in denen der Parser versucht hat, einen datatyp zu erraten, wurden neue Typen zugelassen, die ein Benutzer verwenden kann, um auf natürliche Weise verwendet zu werden.

  2. Zahlreiche Fehlerberichte stellten sich heraus, dass Personen versehentlich den "Vorteil" des automatischen Castings erlangten, wenn sie nicht bemerkten, dass dies der Fall war, was es schwierig machte, ihre Anwendungscodierungserrors zu finden. Nach der Veröffentlichung von 8.3 gab es ungefähr die gleiche Anzahl von Leuten, die angaben, dass die Änderung versteckte Fehler in ihrem eigenen Code aufdeckte, da sich Leute beklagten, dass ihr Code nun Umwandlungen benötigte, wo es vorher nicht war.

Es scheint, dass Sie versucht haben, dieses "Problem" zu lösen, indem Sie implizite Typumwandlungen hinzugefügt haben. Dies ist ein Minenfeld; Ich empfehle es nicht. Sie werden beschränken, welche functionen Sie sicher verwenden können, und Sie werden kein Ende von skurrilen kleinen Bugs haben, die niemand sonst tut, und niemand kann Ihnen einfach helfen. Es ist besser, Ihren Code so zu korrigieren, dass nicht so viele implizite Conversions angenommen werden.

Eine Sache, die Sie verwirren kann, ist, dass in 'PostgreSQL '1.2' kein String-Literal ist. Es ist ein Literal unbekannter Art:

 test = # select pg_typeof ('1.2');
  pg_typeof 
 -----------
  unbekannte
 (1 Reihe)

PostgreSQL versucht, den Typ eines Literals so lange wie möglich aufzulösen, was bei all den neuen datatypen, die ich beschrieben habe, gut funktioniert. Als letzten Ausweg, wenn der timepunkt gekommen ist, an dem der Typ aufgetriggers werden muss und es keine weiteren Hinweise gibt, wird der Typ als text .

 test = # select pg_typeof (case wenn wahr, dann '1.2' sonst null end);
  pg_typeof 
 -----------
  Text
 (1 Reihe)

 test = # select pg_typeof (case wenn true, dann '1.2' sonst 2.3 end);
  pg_typeof 
 -----------
  numerisch
 (1 Reihe)

Problem 2, "Nachbericht", schlägt fehl, da es bei allen impliziten Typumwandlungen, die Sie hinzugefügt haben, mehr als einen möglichen Operator || gibt die je nach den impliziten Typumwandlungen ausgewählt werden könnten, und es gab keine prinzipielle Möglichkeit, zwischen ihnen zu wählen. Wenn Sie die folgende Zeile ändern, sollte sie wieder funktionieren:

 select a || '$'::text || b from test; 

Ich argumentiere, dass es sauberer und sicherer wäre, diese impliziten Umwandlungen nicht hinzuzufügen und den ersten Problemcode zu ändern von:

 select TO_NUMBER('12345678',9999999999.99); 

zu:

 select TO_NUMBER('12345678', '9999999999.99'); 

Immerhin ist dieser zweite Parameter eine Formatzeichenfolge , keine Nummer. Sie können das Zitat nicht weglassen, wenn Sie etwas tun möchten wie:

 test = # select to_number ('12, 454.8- ',' 99G999D9S ');
  zu_number 
 -----------
   -12454.8
 (1 Reihe)