今天看到論壇的一個(gè)帖子,是關(guān)于NVARCHAR2字符串的。解答之后,順便問(wèn)了問(wèn)同事,發(fā)現(xiàn)居然大家都不知道這個(gè)語(yǔ)法。所以這里簡(jiǎn)單描述一下。
其實(shí)語(yǔ)法非常檢查,要指定一個(gè)國(guó)家字符集的字符串NCHAR或NVARCHAR2,只需要在字符串前面加上一個(gè)N就可以了。
舉個(gè)例子:
SQL> CREATE TABLE T_NVARCHAR2 (ID NUMBER, NAME NVARCHAR2(30));
表已創(chuàng)建。
SQL> INSERT INTO T_NVARCHAR2 VALUES (1, N'ABC');
已創(chuàng)建 1 行。
SQL> DROP TABLE T_NVARCHAR2 PURGE;
表已刪除。
SQL> CREATE TABLE T_NVARCHAR2 (ID NUMBER, NAME NVARCHAR2(30));
表已創(chuàng)建。
SQL> INSERT INTO T_NVARCHAR2 VALUES (1, N'ABC');
已創(chuàng)建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT DUMP(NAME, 16) FROM T_NVARCHAR2;
DUMP(NAME,16)
---------------------------------------------------------------------------------------
Typ=1 Len=6: 0,41,0,42,0,43
SQL> SELECT DUMP('ABC', 16) VAR, DUMP(N'ABC', 16) NVAR FROM DUAL;
VAR NVAR
-------------------------------------------- ----------------------------------------
Typ=96 Len=3: 41,42,43 Typ=96 Len=6: 0,41,0,42,0,43
如果對(duì)于VARCHAR2類型的表指定NVARCHAR2類型的查詢,Oracle會(huì)自動(dòng)進(jìn)行隱式類型轉(zhuǎn)換。
SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));
表已創(chuàng)建。
SQL> CREATE INDEX IND_T_NAME ON T(NAME);
索引已創(chuàng)建。
SQL> INSERT INTO T SELECT ROWNUM, OBJECT_NAME FROM ALL_OBJECTS;
已創(chuàng)建54020行。
SQL> COMMIT;
提交完成。
SQL> SET AUTOT ON EXP
SQL> SELECT * FROM T WHERE NAME = 'T';
ID NAME
---------- ------------------------------
53170 T
執(zhí)行計(jì)劃
----------------------------------------------------------
Plan hash value: 1889074194
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T_NAME | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("NAME"='T')
Note
-----
- dynamic sampling used for this statement
SQL> SELECT * FROM T WHERE NAME = N'T';
ID NAME
---------- ------------------------------
53170 T
執(zhí)行計(jì)劃
----------------------------------------------------------
Plan hash value: 2153619298
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 52 (6)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 30 | 52 (6)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYS_OP_C2C("NAME")=U'T')
Note
-----
- dynamic sampling used for this statement
這個(gè)隱式轉(zhuǎn)換過(guò)程會(huì)將列字段的VARCHAR2類型轉(zhuǎn)換為NVARCHAR2類型,導(dǎo)致索引無(wú)法使用。如果想要這種情況下仍然可以使用索引,需要建立一個(gè)函數(shù)索引:
SQL> CREATE INDEX IND_T_NNAME ON T(TO_NCHAR(NAME));
索引已創(chuàng)建。
SQL> SELECT * FROM T WHERE NAME = N'T';
ID NAME
---------- ------------------------------
53170 T
執(zhí)行計(jì)劃
----------------------------------------------------------
Plan hash value: 462587453
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 567 | 60669 | 48 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 567 | 60669 | 48 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T_NNAME | 227 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(SYS_OP_C2C("NAME")=U'T')
Note
-----
- dynamic sampling used for this statement