CHAR的用法

来源:互联网 发布:淘宝退差价流程示意图 编辑:程序博客网 时间:2024/05/16 18:36

1.char是定长存储的,长度不足时会在尾部填补空格,例如CHAR(10),输入'A',会填补9个空格,在SQL中CHAR最多存储2000Bytes,在PL/SQL中最多存储32767Bytes

SQL> create table test (name char(10));

SQL> insert into test values('A');

SQL> select dump(name) from test;


DUMP(NAME)
---------------------------------------------
---------------------------------------------
Typ=96 Len=10: 65,32,32,32,32,32,32,32,32,32 (32表示空格)


2.注意CHAR存储时是按字节还是字符存储

SQL> select * from nls_database_parameters where parameter='NLS_CHARACTERSET';

PARAMETER                      VALUE
------------------------------ -----------------------------------------------
NLS_CHARACTERSET               ZHS16GBK


SQL> CREATE TABLE t (name CHAR(3),memo CHAR(3 CHAR));  --name存储3字节,memo存储3字符

表已创建。

SQL> insert into t values('迈克尔','迈克尔');
insert into t values('迈克尔','迈克尔')
                     *
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."T"."NAME" 的值太大 (实际值: 6, 最大值: 3)

SQL> insert into t values('Mic','迈克尔');

已创建 1 行。

在 ZHS16GBK字符集下,一个汉字算一个字符,占2字节

SQL> select dump(name) dname,dump(memo) dmemo,length(name) lname,length(memo) lmemo from t;

DNAME                                    DMEMO                                                                 LNAME      LMEMO
-------------------------                ----------------------------------------                           ---------- ----------
Typ=96 Len=3: 77,105,99   Typ=96 Len=6: 194,245,191,203,182,251             3          3

3.字符数字的比较

例如:‘40‘,‘1’,‘8’

SQL> select dump('40'),dump('1'),dump('8') from dual;

DUMP('40')                  DUMP('1')               DUMP('8')
-------------------              ----------------            ----------------
Typ=96 Len=2: 52,48 Typ=96 Len=1: 49 Typ=96 Len=1:56

所以'1'<'40'<'8'

如果要按照正常顺序即1<8<40

SQL> with t as
  2  (select '1' id from dual
  3  union
  4  select '40' from dual
  5  union
  6  select '8' from dual)
  7  select * from t order by id+0;  --将id列的字符转为数值型,按数值进行排序,或者order by to_number(id)
 
ID
--
1
8
40

4.CHAR与CHAR的比较

DECLARE v_a CHAR(10):='aaa';
v_b CHAR(3):='aaa';
BEGIN
IF v_a=v_b THEN
DBMS_OUTPUT.PUT_LINE('v_a=v_b');
ELSE
DBMS_OUTPUT.PUT_LINE('v_a<>v_b');
END IF;

END;

比较时v_b会扩大长度到CHAR(10),与v_a的字符类型一致,然后‘aaa       ’=='aaa       '

5.CHAR与VARCHAR2

SQL> var v_name varchar2(10);
SQL> exec :v_name:='aaa'

PL/SQL 过程已成功完成。

SQL> select * from test where name=:v_name;


未选定行

这是因为CHAR遇到VARCHAR2是自动转为VARCHAR2,即CHAR下的‘aaa      ’变成VARCHAR2下的‘aaa      ’,转换时空格不会因为是VARCHAR2自动缩减,而是保留下来,所以当绑定变量'aaa'和'aaa       '比较时,查不出结果,可以使用下列2句之一查询

SQL> select * from test where name=rpad(:v_name,10);  
SQL> select * from test where trim(name)=:v_name;

当在name列建立索引时,使用rpad可以时查询走索引,使用trim导致全表扫描,不走索引,因为等号左边的值的修改,会导致索引失效,只有修改右边的值,除非建立函数索引 create index idx_test on test(trim(name));

SQL> ALTER TABLE TEST MODIFY NAME VARCHAR2(20);

表已更改。

SQL> SELECT * FROM test;

NAME
--------------------
aaa

SQL> select length(name) from test;

LENGTH(NAME)
------------
          10

这里可以看出CHAR转为VARCHAR2时,空格被保留下来,dump(name),结果是Typ=1 Len=10: 97,97,97,32,32,32,32,32,32,32

6.在JDBC中,如果使用绑定变量,对CHAR类型字段查询时,容易出错,Java中只有String,不管CHAR还是VARCHAR2

 String pwd="owen";            String username="scott";            //String sql="select * from test where name=?";            String sql = "select * from test where name=rpad(?,10)";  //这句话是正确的,可以查询出aaa,上一句结果No data            String url = "jdbc:oracle:thin:@localhost:1521:orcl";            Class.forName("oracle.jdbc.driver.OracleDriver");            Connection conn = DriverManager.getConnection(url, username, pwd);            PreparedStatement pstmt = conn.prepareStatement(sql);            pstmt.setString(1,"aaa");            ResultSet rs = pstmt.executeQuery();            if(rs.next()){                String gender = rs.getString("name");                System.out.println(gender);            }            else{                System.out.println("No data");            }


总结:CHAR类型尽量不要使用,改用VARCHAR2比较好,CHAR会导致很多看不见的麻烦


0 0
原创粉丝点击