sql >> Databáze >  >> RDS >> Oracle

Jak funguje číselné srovnání na sloupci Oracle VARCHAR?

Jak je uvedeno v Reference jazyka SQL :

Pokud se typy neshodují, provede se ve sloupci tabulky implicitní převod. To lze vidět trasováním v SQL*Plus s některými fiktivními daty.

create table t42 (foo varchar2(3 byte));
insert into t42 (foo) values ('10');
insert into t42 (foo) values ('2A');
set autotrace on explain

Toto funguje:

select * from t42 where foo = '10';

FOO
---
10

Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     3 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T42  |     1 |     3 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("FOO"='10')

Note
-----
   - dynamic sampling used for this statement (level=2)

Ale tyto chyby:

select * from t42 where foo = 10;

ERROR:
ORA-01722: invalid number



Execution Plan
----------------------------------------------------------
Plan hash value: 3843907281

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     3 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T42  |     1 |     3 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_NUMBER("FOO")=10)

Všimněte si rozdílu ve filtru; filter("FOO"='10') versus filter(TO_NUMBER("FOO")=10) . V druhém případě, v porovnání s číslem, to_number() se provádí proti každému řádku v tabulce, výsledek tohoto převodu se porovnává s pevnou hodnotou. Pokud tedy některou z hodnot znaků nelze převést, získáte ORA-01722. Aplikovaná funkce také zastaví používání indexu, pokud je v tomto sloupci přítomen.

Zajímavé je, že máte více než jeden filtr. Oracle je může vyhodnocovat v různých pořadích v různých časech, takže ORA-01722 nemusíte vždy vidět a někdy se objeví. Řekněme, že jste měli where foo = 10 and bar = 'X' . Kdyby si Oracle myslel, že by mohl odfiltrovat non-X hodnoty, použije pouze to_number() k tomu, co zbývá, a tento menší vzorek nemusí mít nečíselné hodnoty v foo . Ale pokud máte and bar = 'Y' , jiné než Y hodnoty mohou zahrnovat jiné než číselné hodnoty, nebo Oracle může filtrovat podle foo první , v závislosti na tom, jak selektivní považuje hodnoty za.

Morálkou je nikdy neukládat číselné informace jako typ znaku.

Hledal jsem odkaz AskTom na podporu morálky a první, na kterou jsem se podíval příhodně odkazuje na efekt „změny v pořadí predikátu“ a také na „neukládejte čísla do varchar2“.



  1. Jak zachytit chybové záznamy pomocí JDBCTemplate batchUpdate v postgreSql?

  2. Jak se připojit ke vzdálenému serveru MySQL přes SSH pomocí JPA?

  3. Jak zkontrolovat přepínače

  4. Přepíše název cizího klíče spojeného dědičnosti pomocí JPA/Hibernate