1. 程式人生 > >ORACLE隱式型別轉換

ORACLE隱式型別轉換

 

隱式型別轉換簡介

 

通常ORACLE資料庫存在顯式型別轉換(Explicit Datatype Conversion和隱式型別轉換(Implicit Datatype Conversion)兩種型別轉換方式。如果進行比較或運算的兩個值的資料型別不同時(源資料的型別與目標資料的型別),而且此時又沒有轉換函式時,那麼ORACLE必須將其中一個值進行型別轉換,使其能夠運算。這就是所謂的隱式型別轉換。其中隱式型別轉換是自動進行的,當然,只有在這種轉換是有意義的時候,才會自動進行。

 

Data Conversion

Generally an expression cannot contain values of different datatypes. For example, an expression cannot multiply 5 by 10 and then add 'JAMES'. However, Oracle supports both implicit and explicit conversion of values from one datatype to another.

 

 

關於隱式型別轉換,建議翻看官方文件“Data Type Comparison Rules”章節,下面是官方文件中的隱式型別轉換矩陣。從下面這個表格,我們就能對哪些資料型別能進行轉換一目瞭然。

 

 

 

 

 

隱式轉換的規則:

 

 

其實隱式型別轉換髮生在很多地方,只是我們很多時候沒有留意罷了,不打算一一舉例,自行翻閱官方文件的介紹,摘抄隱式型別轉換的一些常見的規則如下:

 

The following rules govern implicit data type conversions:

  • During INSERT and UPDATE operations, Oracle converts the value to the data type of the affected column.
  • During SELECT FROM operations, Oracle converts the data from the column to the type of the target variable.
  • When manipulating numeric values, Oracle usually adjusts precision and scale to allow for maximum capacity. In such cases, the numeric data type resulting from such operations can differ from the numeric data type found in the underlying tables.
  • When comparing a character value with a numeric value, Oracle converts the character data to a numeric value.
  • Conversions between character values or NUMBER values and floating-point number values can be inexact, because the character types and NUMBER use decimal precision to represent the numeric value, and the floating-point numbers use binary precision.
  • When converting a CLOB value into a character data type such as VARCHAR2, or converting BLOB to RAW data, if the data to be converted is larger than the target data type, then the database returns an error.
  • During conversion from a timestamp value to a DATE value, the fractional seconds portion of the timestamp value is truncated. This behavior differs from earlier releases of Oracle Database, when the fractional seconds portion of the timestamp value was rounded.
  • Conversions from BINARY_FLOAT to BINARY_DOUBLE are exact.
  • Conversions from BINARY_DOUBLE to BINARY_FLOAT are inexact if the BINARY_DOUBLE value uses more bits of precision that supported by the BINARY_FLOAT.
  • When comparing a character value with a DATE value, Oracle converts the character data to DATE.
  • When you use a SQL function or operator with an argument of a data type other than the one it accepts, Oracle converts the argument to the accepted data type.
  • When making assignments, Oracle converts the value on the right side of the equal sign (=) to the data type of the target of the assignment on the left side.
  • During concatenation operations, Oracle converts from noncharacter data types to CHAR or NCHAR.
  • During arithmetic operations on and comparisons between character and noncharacter data types, Oracle converts from any character data type to a numeric, date, or rowid, as appropriate. In arithmetic operations between CHAR/VARCHAR2 and NCHAR/NVARCHAR2, Oracle converts to a NUMBER.
  • Most SQL character functions are enabled to accept CLOBs as parameters, and Oracle performs implicit conversions between CLOB and character types. Therefore, functions that are not yet enabled for CLOBs can accept CLOBs through implicit conversion. In such cases, Oracle converts the CLOBs to CHAR or VARCHAR2 before the function is invoked. If the CLOB is larger than 4000 bytes, then Oracle converts only the first 4000 bytes to CHAR.
  • When converting RAW or LONG RAW data to or from character data, the binary data is represented in hexadecimal form, with one hexadecimal character representing every four bits of RAW data. Refer to "RAW and LONG RAW Data Types" for more information.
  • Comparisons between CHAR and VARCHAR2 and between NCHAR and NVARCHAR2 types may entail different character sets. The default direction of conversion in such cases is from the database character set to the national character set. Table 2-9 shows the direction of implicit conversions between different character types.

 

對上面官方文件資料的翻譯如下,如有不對或不夠確切的地方,敬請指出

 

1.  對於INSERT和UPDATE操作,ORACLE會把插入值或者更新值隱式轉換為對應欄位的資料型別。

 

2.  對於SELECT語句,ORACLE會把欄位的資料型別隱式轉換為變數的資料型別。

 

3.  當處理數值時,ORACLE通常會調整精度和小數位,以實現最大容量。在這種情況下,由此類操作產生的數字資料型別可能與在基礎表中找到的數字資料型別不同。

 

4.  當比較一個字元型和數值型的值時,ORACLE會把字元型的值隱式轉換為數值型。

 

5.  字元值或NUMBER值與浮點數值之間的轉換可能不準確,因為字元型別和NUMBER使用十進位制精度表示數字值,而浮點數則使用二進位制精度。

 

6.  將CLOB值轉換為字元資料型別(例如VARCHAR2)或將BLOB轉換為RAW資料時,如果要轉換的資料大於目標資料型別,則資料庫將返回錯誤。

 

7.   當timestamp型別轉換為DATE時(按照第三條,隱式轉換不應該把timestamp轉換為date,除非insert這樣的),timestamp後幾位會被truncated忽略,至於忽略幾位,取決於資料庫版本。

 

8.  從BINARY_FLOAT到BINARY_DOUBLE的轉換是準確的。

 

9.  從BINARY_DOUBLE到BINARY_FLOAT的轉換是不精確的,因為BINARY_DOUBLE精度更高。

 

10.  當比較字元型和日期型的資料時,ORACLE會把字元型轉換為日期型。

 

11. 如果呼叫函式(過程)或運算子操作時,如果輸入引數的資料型別與函式(儲存過程)定義的引數資料型別不一致或不是可接受的資料型別時,則ORACLE會把輸入引數的資料型別轉換為函式或者過程定義的資料型別。

 

12. 當使用賦值符號(等號)時,右邊的型別轉換為左邊的型別

 

13. 當連線操作(concatenation,一般為||)時,ORACLE會隱式轉換非字元型到字元型

 

14. 如果字元型別的資料和非字元型別的資料(如number、date、rowid等)作算術運算,則ORACLE會將字元型別的資料轉換為合適的資料型別,這些資料型別可能是number、date、rowid等。

  如果CHAR/VARCHAR2 和NCHAR/NVARCHAR2之間作算術運算,則ORACLE會將她們都轉換為number型別的資料再做比較。

 

 

15. 比較CHAR/VARCHAR2 和NCHAR/NVARCHAR2時,如果兩者字符集不一樣,則預設的轉換方式是將資料編碼從資料庫字符集轉換為國家字符集

 

 

下面簡單舉兩個例子,看看隱式轉換髮生的場景:

 

例子:

 

SQL> create table test(object_id varchar2(12), object_name varchar2(64));
 
Table created.
 
SQL> insert into test
  2  select object_id, object_name from dba_objects;
 
63426 rows created.
 
SQL> commit;
 
Commit complete.
 
SQL> create index ix_test_n1 on test(object_id);
 
Index created.
 
SQL> select count(*) from test where object_id=20;
 
  COUNT(*)
----------
         1
 
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
 
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
SQL_ID  4bh7yzj5ma0ks, child number 0
-------------------------------------
select count(*) from test where object_id=20
 
Plan hash value: 1950795681
 
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |    45 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |     8 |            |          |
 
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
|*  2 |   TABLE ACCESS FULL| TEST |     3 |    24 |    45  (20)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(TO_NUMBER("OBJECT_ID")=20)
 
Note
-----
   - dynamic sampling used for this statement
 
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------
 
23 rows selected.

 

如上所示,這個發生隱式轉換是因為這個規則: “當比較一個字元型和數值型的值時,ORACLE會把字元型的值隱式轉換為數值型”(對於SELECT語句,ORACLE會把欄位的資料型別隱式轉換為變數的資料型別。似乎這個規則也對),此時由於隱式轉換髮生在OBJECT_ID欄位上(TO_NUMBER("OBJECT_ID")),導致執行計劃走全表掃描。如果我們稍微修改一下SQL的寫法,就會發現執行計劃會走INDEX RANGE SCAN。 如下所示:

 

SQL>  select count(*) from test where object_id='20';
 
  COUNT(*)
----------
         1
 
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  7800f6da7c909, child number 0
-------------------------------------
 select count(*) from test where object_id='20'
 
Plan hash value: 4037411162
 
--------------------------------------------------------------------------------
| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |            |     1 |     6 |            |          |
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|*  2 |   INDEX RANGE SCAN| IX_TEST_N1 |     1 |     6 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"='20')
 
 
            
           

相關推薦

ORACLE型別轉換 ORA-01722: 無效數字

在做開時經常會遇到ORA-01722: 無效數字 的錯誤,原因在於自動型別轉換出錯.下面舉個例子: CREATE TABLE t1(NAME VARCHAR(2)); INSERT INTO t1 VALUES('a'); INSERT INTO t1 VALUES('b

ORACLE型別轉換

  隱式型別轉換簡介   通常ORACLE資料庫存在顯式型別轉換(Explicit Datatype Conversion)和隱式型別轉換(Implicit Datatype Conversion)兩種型別轉換方式。如果進行比較或運算的兩個值的資料型別不同時(源資料的型別與目標資料的型別)

Mysql精度損失--型別轉換的坑

    今天在工作中遇到一個小問題,很不起眼的問題,但是很嚴重.就是mysql精度損失.    為什麼我們在進行mysql操作的時候要加引號呢?通常都是字串需要加引號,而數字就不需要加引號,但是這次我在純數字的字串中沒有加引號,所以問題就出現.  

C++:型別轉換和關鍵字explicit

《Inside the C++ Object Model》第二章開篇處有這樣一段話:“事實上關鍵字explicit之所以被匯入這個語言,就是為了給程式設計師提供一種方法,使他們能夠制止“單一引數的constructor”被當做一個conversion運算子”。 conversion運算子即型別

一道有趣的JS題(1 - 妙用型別轉換

題目 輸入:var a = [1,[2,3],a,[b,c]]; 輸出:1,2,3,a,b,c 解決方法3種 1. 使用遞迴 function flat1(arr){ let res = []; if( Array.isArray(arr) ){ arr.for

C++型別轉換 operator

在Win32 SDK, 該API函式原型為 BOOL GetClientRect( HWND hWnd, // 視窗控制代碼 LPRECT lpRect // 客戶區座標 ); 在MFC中,該函式的原型為void

JavaScript中的型別轉換

最近在學習渡一教育的JavaScript精品課,成哥講的還是很棒的,開這個系列記錄下學習筆記 本次學習筆記,對應web前端開發JavaScript精英課js的第六課時   目錄  一.is NaN()  二.++ -- 自增自減運算子 &nb

有趣的JavaScript型別轉換

---恢復內容開始--- 有趣的JavaScript隱式型別轉換 JavaScript的資料型別是非常弱的(不然不會叫它做弱型別語言了)!在使用算術運算子時,運算子兩邊的資料型別可以是任意的,比如,一個字串可以和數字相加。之所以不同的資料型別之間可以做運算,是因為JavaScript引擎在運算之前會悄悄的

MySQL型別轉換導致索引失效

今天發現一個問題,where條件的列上明明有索引,但是執行計劃還是走全表掃描 mysql>  explain select task_id FROM mostop_xiaodai_collection_call_auto WHE

Javascript 型別轉換規則

1. Javascript隱式型別轉換與Java的區別 一個Javascript表示式中包含不同型別的值進行運算時,可能會發生隱式型別轉換,也可能不轉換,隱式型別轉換規則與運算元,運算子都相關,這是與強型別語言(Java)不同的地方,Java隱式型別一般只與運算元相關,即表數範圍小的型別向表

Qt——QVariant型別轉換實現型別系統(Type System)

QVariant v(709); qDebug() << v.toInt(); QVariant w("How are you! "); qDebug()

JavaScript面試題大坑之型別轉換例項程式碼

1.1-隱式轉換介紹 在js中,當運算子在運算時,如果兩邊資料不統一,CPU就無法計算,這時我們編譯器會自動將運算子兩邊的資料做一個數據型別轉換,轉成一樣的資料型別再計算 這種無需程式設計師手動轉換,而由編譯器自動轉換的方式就稱為隱式轉換 例如1 > "0"這行程式碼在js中並不會報

C++進階--型別轉換

//############################################################################ /* 隱式型別轉換 * * 型別轉換可分為: * 隱式

15 More Effectic C++ ——條款21/22(過載防止型別轉換/使用複合操作符)

1 看不見的隱式型別轉換 當建構函式只有一個,編譯器會利用建構函式進行隱式型別轉換。如下面所示: class UInt { public: UInt(); UInt(int value); } UInt a = 0, b(0), c = 1; // 隱式轉換:int變成UI

JavaScript強制型別轉換型別轉換

在JavaScript中宣告變數不需指定型別, 對變數賦值也沒有型別檢查,同時JavaScript允許隱式型別轉換。這些特徵說明JavaScript屬於弱型別的語言。 (1).轉換為字串 轉換為字串是應用程式中的常見操作,javascript提供了toStr

C語言進階學習1 型別轉換和強制型別轉換

本部落格記錄狄泰學院課程的學習 學習交流群:320628659 個人QQ:1367087622 歡迎大家交流學習 本章的學習目標: 學習隱式型別轉換和強制型別轉換的基本概念. 本意或非本意下使用型別轉換時可能會出現的問題. 在C語言是可以進行型別之間的轉換且其中存在兩種型別

JavaScript顯型別轉換型別轉換

本文談談JavaScript的型別轉換,我們知道在JavaScript中宣告變數不需指定型別, 對變數賦值也沒有型別檢查,同時JavaScript允許隱式型別轉換。這些特徵說明JavaScript屬於弱型別的語言。 在強型別的C++中,多數情況下建構函式需要宣告為exp

Operator運算子過載與Implicit型別轉換

class Person { public int Age { get; set; } public string Name { get; set; } public static int operator -(Per

由於mysql型別轉換導致的索引失效的問題

今天在測試執行計劃時,發現了以下問題: mysql 1739 due to type or collation conversion on field user表: 主鍵userId和us

C++------型別轉換

隱式型別轉換的定義: “可以用 單個形參來呼叫 的建構函式定義了從 形參型別 到 該類型別 的一個隱式轉換。” 這裡應該注意的是, “可以用單個形參進行呼叫” 並不是指建構函式只能有一個形參,而是它可以有多個形參,但那些形參都是有預設實參的。 那麼,什麼是“隱式轉換”呢? 上面這句話也說了,