当前位置:  数据库>oracle

从Java的类型转换看MySQL和Oracle中的隐式转换

    来源: 互联网  发布时间:2017-06-20

    本文导语: 说起数据类型转换,在开发中如此,在数据库中也是如此,之前简单对比过MySQL和Oracle的数据类型转换情况,可以参见MySQL和Oracle中的隐式转换 不过当时写完之后,有个读者随口问了一句为什么,为什么呢?似乎自己还是一知半...

说起数据类型转换,在开发中如此,在数据库中也是如此,之前简单对比过MySQL和Oracle的数据类型转换情况,可以参见MySQL和Oracle中的隐式转换
不过当时写完之后,有个读者随口问了一句为什么,为什么呢?似乎自己还是一知半解,说是规则,无规矩不成方圆,倒也无可非议,不过我觉得还是要再看看,看看还能有哪些收获,接下来的内容我就不能保证正确性了,希望大家明辨,也希望提出意见,毕竟就是希望把问题搞明白而已。

 首先开发语言中就有数据类型的隐式转换,这一点在java中尤为明显,毕竟一个承载了太多使命的语言如此庞大,又是强类型语言,数据类型的转换就是一个尤为重要的部分了。Java中的数据类型转换主要有下面的规则。
//转换规则:从存储范围小的类型到存储范围大的类型。
//具体规则为:byte→short(char)→int→long→float→double
自己也嘚瑟了一下,写了个简单的小程序以示明证,这个程序不能说明我会java.
 public class Test {
 public static void main(String args[]){
 /*1*/    System.out.println("aa");
/*2*/    System.out.println('a');
/*3*/    byte a=10;
/*4*/    System.out.println(a);
/*5*/    char b='b';
/*6*/    int c=b;
/*7*/    System.out.println(b);
/*8*/    System.out.println(c);
    }
 }
这个程序的输出为
aa
 a
 10
 b
 98

这样写的目的就是,
 第1行,第2行中的单引号,双引号需要做的事情就是标示它是一个变量值,两者的效果在这个时候是一致的。
 第3行初始化了一个byte变量,然后输出,这个时候还是byte
但是第5行声明了一个char型变量,然后在第6行中做了类型的隐式转换,在第7行中输出为字符b,但是在第8行输出为
 通过这个简单的例子可以发现确实数据类型做了隐式转换,而且单引号,双引号在这个例子中的作用是一致的,就是标示变量。
 因为在Java中查看数据类型的转换代价还是相对要困难一些,我们可以在数据库中来类比。
 首先还是重复之前的测试,准备一批的数据。创建一个表,然后插入一些值。
create table test (id1 number,id2 varchar2(10));
  begin                 
    for i in 1..100 loop
    insert into test values(i,chr(39)||i||chr(39));
    end loop;
    commit;
    end;
    /
 create index ind1_test on n1.test(id1);
 create index ind2_test on n1.test(id2);
然后收集统计信息。
exec dbms_stats.gather_table_stats('TEST','TEST',CASCADE=>TRUE);
这个时候查看执行计划
explain plan for select *from test where id1='2';
 SQL>  select *from table(dbms_xplan.display);
 PLAN_TABLE_OUTPUT
 ----------------------------------------------------------------------------------------------------
 Plan hash value: 2759464289
 -----------------------------------------------------------------------------------------
 | Id  | Operation                  | Name      | Rows  | Bytes | Cost (%CPU)| Time    |
 -----------------------------------------------------------------------------------------
 |  0 | SELECT STATEMENT            |          |    1 |    20 |    1  (0)| 00:00:01 |
 |  1 |  TABLE ACCESS BY INDEX ROWID| TEST      |    1 |    20 |    1  (0)| 00:00:01 |
 |*  2 |  INDEX RANGE SCAN          | IND1_TEST |    1 |      |    1  (0)| 00:00:01 |
 -----------------------------------------------------------------------------------------
 Predicate Information (identified by operation id):
 PLAN_TABLE_OUTPUT
 -------------------------------------------------------------
    2 - access("ID1"=2)
通过这个确实可以看到谓词信息的部分    2 - access("ID1"=2) 已经自动做了转换,这个时候一个触发了一个索引扫描。
 但是这个过程还是看不出有数据类型转换的痕迹,我们做一个看似有问题的例子,来触发一下。尽管id1位int型,但是使用字符型来触发。
SQL>    explain plan for select *from test where id1='A';
 Explained.
 SQL>  select *from table(dbms_xplan.display);
 PLAN_TABLE_OUTPUT
 ----------------------------------------------------------------------------------------------------
 Plan hash value: 2759464289
 -----------------------------------------------------------------------------------------
 | Id  | Operation                  | Name      | Rows  | Bytes | Cost (%CPU)| Time    |
 -----------------------------------------------------------------------------------------
 |  0 | SELECT STATEMENT            |          |    1 |    20 |    1  (0)| 00:00:01 |
 |  1 |  TABLE ACCESS BY INDEX ROWID| TEST      |    1 |    20 |    1  (0)| 00:00:01 |
 |*  2 |  INDEX RANGE SCAN          | IND1_TEST |    1 |      |    1  (0)| 00:00:01 |
 -----------------------------------------------------------------------------------------
 Predicate Information (identified by operation id):
 PLAN_TABLE_OUTPUT
 ------------------------------------------------
    2 - access("ID1"=TO_NUMBER('A'))
可以看到谓词信息已经发生了变化。  2 - access("ID1"=TO_NUMBER('A'))从这个地方我们可以看到确实触发了一个to_number的操作。
 而优化器在这个时候虽然触发了,但是在sql运行的时候,就会报出错误,这个时候可以看到Oracle还是蛮严谨的。
SQL> select *from test where id1='A';
 select *from test where id1='A'
                            *
 ERROR at line 1:
 ORA-01722: invalid number
而如果使用双引号,生成执行计划都会抛错。
SQL> explain plan for select *from test where id1="A";
explain plan for select *from test where id1="A"
                                            *
ERROR at line 1:
ORA-00904: "A": invalid identifier
可见单引号和双引号在Oracle代表的含义还是有很大差别。

 我们来看看在MySQL中的表现。
 还是创建一个简单的表,插入一些数据。
> create table test (id1 int,id2 varchar(10));
 > insert into test values(1,'1');
 > insert into test values(2,'2');
 > insert into test values(3,'3');
 > commit;
 > create index idx_id1 on test(id1);
 > create index idx_id2 on test(id2);
这个时候生成执行计划,可以发现走了索引
> explain select * from test where id1='1';
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 | id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra      |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 |  1 | SIMPLE      | test  | ref  | idx_id1      | idx_id1 | 5      | const |    1 | Using where |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 1 row in set (0.00 sec)
而如果查看id1为varchar的类型时,也走了索引。
> explain select * from test where id1='a';
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 | id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra      |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 |  1 | SIMPLE      | test  | ref  | idx_id1      | idx_id1 | 5      | const |    1 | Using where |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 1 row in set (0.00 sec)
差别更大的就是如果使用id1='a',也能够正常执行,只是没有任何匹配的记录。
> select * from test where id1='a';
 Empty set (0.00 sec)
而如果由单引号改为双引号,也能够正常运行。
> select * from test where id1="a";
 Empty set (0.00 sec)
而且双引号的情况下,生成执行计划也没有问题。
> explain select * from test where id1="a";
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 | id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra      |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 |  1 | SIMPLE      | test  | ref  | idx_id1      | idx_id1 | 5      | const |    1 | Using where |
 +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
 1 row in set (0.00 sec)
可以看出在MySQL中这个时候的范围似乎更宽,在MySQL中不光用单引号,双引号,而且还经常会看到·这种符号。
 这种在MySQL中可以灵活声明一些变化个,举个不太恰当的例子,比如我们创建一个表,一个字段为int,类型为int直接按照下面的方式来写,肯定抛错。
> create table test1(int int);
 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'int int)' at line 1
 crea' at line 1
可以加上·,就可以识别了。
> create table test1(`int` int);
 Query OK, 0 rows affected (0.00 sec)

这个对比的跨度有点大,但是通过一些小把戏似乎还是能够看出在这些类型的转换中,优化器这边的触发情况。再接再厉,继续探究。


    
 
 

您可能感兴趣的文章:

  • java中如何将ascII 码转换成字符以及将字符转换成ascII码? 在线等待加分!
  • 如何将java.util.Date类型的日期转换成java.sql.Date类型的日期?
  • 我在jbuilder中新建一个servlet,源程序为java文件,是怎么从java到servler转换的?
  • 在java中,怎么将UTF-8码转换为GB码?
  • java自定义枚举转换器示例
  • Java对象转换库 EZMorph
  • java DocConverter.jar转换word文档到pdf 中文乱码问题
  • java数据转换的问题
  • 一个关于java写的web应用如何转换平台的问题,急急急!!
  • java中强制转换
  • java数据类型的转换问题。
  • Java 繁简字体转换问题!!!急!!!
  • 对面的大虾看过来:sql到java的类型转换?
  • 求助java中如何在unicode和GBK2312之间转换
  • 在java中如何实现String到int型的转换???用什么方法???
  • Java到C++的转换工具 J2cpp
  • 怎样将标准的C++代码转换成JAVA代码??
  • Java中的一个转换成asc码函数?
  • 请问,如何用java程序转换xsl?
  • 怎样把String转换成int?怎样获得系统时间并转换成java.sql.date类型?
  • java命名空间javax.xml.ws注释类型webserviceref成员方法: type定义参考
  • java 基本类型或可序列化类型,这里说的可序列化类型是什么意思???具体都有哪些类型??谢谢
  • java命名空间javax.annotation注释类型resource的类成员方法: authenticationtype定义及介绍
  • 请问SQL中的datetime类型于java中什么类型对应?
  • java命名空间javax.annotation注释类型resource的类成员方法: type定义及介绍
  • java中的字符类型如何转换成String类型
  • java命名空间javax.xml.ws注释类型webserviceref成员方法: value定义参考
  • 请教JAVA小问题:如何将含数字的String类型的对象转化为int或long类型
  • java命名空间javax.annotation注释类型resource的类成员方法: shareable定义及介绍
  • ado的rs.field("字段名")可以访问任何类型的数据,那吗java里面这种问题如何处理。是不是要先判断类型然后再根据类型来使用相应的getint or getString阿!谢谢了!在线等待!
  • java命名空间javax.jws注释类型webparam的类成员方法: mode定义及介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • com.Oracle.*;是指相对于当前目录下的COM下的ORACLE吗?java是怎么寻找PACKAGE的?
  • Linux系统下利用java连接Oracle 10G
  • 再问java 连接oracle 问题,急!
  • oracle和Java的连接,急!!
  • JAVA连接ORACLE问题(100分)
  • 怎么在java里调用一个oracle的procedure呢?
  • java与oracle
  • FSF反对Oracle起诉Google侵犯Java专利的起诉
  • 怎么在java中向一个sql语句传参数,就像oracle的proc一样啊?
  • 为什么在编译java程序的时候出现oracle.jdbc.driver不存在?急!!!
  • 如何获取java连接oracle的驱动?
  • 听ORACLE网站上说8.1.6有支持jdbc2.0的JAVA2驱动
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分 iis7站长之家
  • 在java中能不能调用oracle的package
  • 求教 JAVA 连Oracle数据库。
  • 请教一个关于java中连接远程oracle数据库的问题
  • redhat 9 下安装 oracle9i 过程中,要求指定java目录,到底是哪一个目录?
  • 请问如何用Java从Oracle数据库中读取媒体文件,如图片,mpeg 等
  • 请教怎样在虚拟机中的linux系统安装 Java环境以及Oracle
  • 谁有java编写的连接 oracle9i的例子 急100
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 我对JAVA一窍不通,可惜别人却给我一个Java的project,要我做一个安装程序,请问哪里有JAVA INSTALLER下载,而且我要不要安装java的sdk才能完成此项任务?
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: stringflavor定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3