2012-03-27 1 views
7

Ich fand dieses seltsame Verhalten, und ich bin mir dabei mit dem Kopf ... jemand hat irgendwelche Ideen?Wählen Sie die Zeichenfolge als Zahl auf Oracle

Oracle 10g: Ich habe zwei verschiedene Tabellen, haben beide diese Spalte mit dem Namen "TESTCOL" als Varchar2 (10), keine Nullwerte enthalten.

Wenn ich diese Abfrage auf tabelle1 ausführen, ich die richtigen Ergebnisse zu erhalten:

select * from table1 where TESTCOL = 1234; 

Hinweis, die ich setzen gerade nicht ‚1234‘ ... es ist kein Tippfehler, das ist ein dynamisch generierte Abfrage und ich werde versuchen, sie nicht zu ändern (zumindest nicht in naher Zukunft).

Aber, wenn ich die gleiche Abfrage ausführen, auf table2, erhalte ich diese Fehlermeldung:

ORA-01722: Invalid number 

Beiden Abfragen auf der gleichen Sitzung, dieselbe Datenbank ausgeführt werden.

Ich habe diese beiden Tabellen durch diese Spalte verbunden und der Join funktioniert ok, das einzige Problem zeigt, wenn ich versuche, diese Bedingung zu verwenden.

Irgendwelche Ideen auf, was von einer Tabelle zur anderen unterschiedlich sein könnte?

Vielen Dank im Voraus.

Antwort

22

Wenn TESTCOL Nicht-Nummern enthält, kann Oracle Probleme beim Konvertieren von TESTCOL Einträge in Zahlen auftreten. Denn was es tut, intern, ist dies:

select * from table1 where TO_NUMBER(TESTCOL) = 1234; 

Wenn Sie so sicher sind, dass 1234 nicht als ein VARCHAR wörtliche ausgedrückt wird, dann versuchen Sie stattdessen, um varchar Werte, anstatt numerisch diejenigen zu vergleichen:

select * from table1 where TESTCOL = TO_CHAR(1234); 
3

Sie treffen hier die Gefahren der impliziten Typumwandlung.

Mit dem Ausdruck testcol = 1234 geben Sie an, dass Sie testcol als numerische Spalte behandeln möchten, daher versucht Oracle, alle Werte in dieser Spalte in eine Zahl zu konvertieren.

Der ORA-01722 tritt auf, weil anscheinend mindestens ein Wert in dieser Spalte nicht eine Zahl ist.

Auch wenn Sie behaupten, dass dies "kein Tippfehler" ist, ist es tatsächlich eins. Es ist ein syntaktischer Fehler.

Sie Ihre Parameter als Stringliteral mit einfachen Anführungszeichen zu erklären haben: where testcol = '1234'

einen korrekten Zustand zu schaffen, ist die einzige Lösung für Ihr Problem.

4

Nun offensichtlich TABLE2.TESTCOL enthält Werte, die sind keine Zahlen.Der Vergleich einer Zeichenfolge mit einem numerischen Literal generiert eine implizite Konvertierung. Daher kann jeder Wert in TESTCOL, der nicht auf eine Zahl gewandelt werden kann, ORA-1722 werfen.

Es trifft Sie nicht, wo Sie die zwei Tabellen vergleichen, weil Sie Zeichenfolgen vergleichen.

Sie haben also ein paar Optionen, von denen Sie nicht mögen. Die naheliegendste Antwort ist das Reinigen der Daten, so dass TABLE2 keine Nicht-Numerik enthält. Idealerweise sollten Sie dies kombinieren, indem Sie die Spalte in einen numerischen Datentyp ändern. Andernfalls können Sie den Generator so ändern, dass er Code erzeugt, den Sie gegen ein Shonky-Datenmodell ausführen können. In diesem Fall bedeutet das, dass Literale in Anführungszeichen eingeschlossen werden, wenn die zugeordnete Spalte einen Zeichendatentyp hat.

-1

Folgendes sollte funktionieren. Ersetzen Sie einfach das "Ihre wo".

select * 
from table1 
where (select TO_NUMBER(TESTCOL) 
     from table2 
     where "your where") = 1234;