[20170516]nvl与非NULL约束.txt
[20170516]nvl与非NULL约束.txt
--前几天做的测试http://blog.itpub.net/267265/viewspace-2137853/,实际上差异没有这个大,因为第2个多数是常量.
--今天测试nvl与非NULL约束的问题.
1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
SCOTT@book> create table t as select rownum id,'test' name , 0 flag_num ,lpad('0',1,'0') flag_varchar from dual connect by level<=2e4;
Table created.
SCOTT@book> update t set flag_num=1, flag_varchar='1' where id=1e4 or id=2e4;
2 rows updated.
SCOTT@book> commit ;
Commit complete.
--//分析表略.
--//选择lpad函数,这样数据类型varchar2.
SCOTT@book> @ &r/desc t
Name Null? Type
-------------- -------- -------------
1 ID NUMBER
2 NAME CHAR(4)
3 FLAG_NUM NUMBER
4 FLAG_VARCHAR VARCHAR2(1)
--//首先我一直建议开发对于表示状态的字段最好选择varchar2(1).因为选择数字除了0占用1个字节长度外,其他至少是2.这样建立对于磁盘空间,以及建立的
--//索引都会减少空间占用.
--//我还见过使用-1表示状态的,实际上许多开发不太了解oracle一些数字类型的存储结构.-1占3个字节
SCOTT@book> select dump(-1,16) from dual ;
DUMP(-1,16)
---------------------
Typ=2 Len=3: 3e,64,66
2.首先讲我遇到的常见错误.
SCOTT@book> alter session set statistics_level=all ;
Session altered.
--首先就是隐式转换的问题
SCOTT@book> select dump(nvl(1,'1'),16) from dual ;
DUMP(NVL(1,'1'),1
-----------------
Typ=2 Len=2: c1,2
SCOTT@book> select dump(nvl('1',1),16) from dual ;
DUMP(NVL('1',1)
---------------
Typ=1 Len=1: 31
--//你可以发现类型向第1个参数类型转换.
SCOTT@book> select * from t where nvl(flag_varchar,0)=1;
ID NAME FLAG_NUM F
---------- -------------------- ---------- -
10000 test 1 1
20000 test 1 1
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 0vv5wtp6q8ay5, child number 0
-------------------------------------
select * from t where nvl(flag_varchar,0)=1
Plan hash value: 1601196873
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 17 (100)| | 2 |00:00:00.01 | 55 |
|* 1 | TABLE ACCESS FULL| T | 1 | 200 | 2600 | 17 (0)| 00:00:01 | 2 |00:00:00.01 | 55 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER(NVL("FLAG_VARCHAR",'0'))=1)
23 rows selected.
--//你可以发现这样情况在开发中很常见.如果写成如下:
SCOTT@book> select * from t where nvl(flag_varchar,0)='1';
ID NAME FLAG_NUM F
---------- -------------------- ---------- -
10000 test 1 1
20000 test 1 1
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 9y06mwu7wncxx, child number 0
-------------------------------------
select * from t where nvl(flag_varchar,0)='1'
Plan hash value: 1601196873
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 17 (100)| | 2 |00:00:00.01 | 55 |
|* 1 | TABLE ACCESS FULL| T | 1 | 10000 | 126K| 17 (0)| 00:00:01 | 2 |00:00:00.01 | 55 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NVL("FLAG_VARCHAR",'0')='1')
--//你仔细看实际上oracle filter变成了 (NVL("FLAG_VARCHAR",'0')='1'),注意0变成'0'.建立开发统一类型这种表示状态的最好选择varchar2.
--//这样在编程时就知道是字符类型,带入参数,以及最后的等于数值选择字符类型.看看我们的开发团队就明白这个问题的严重性!!而不
--//会出现这样的情况
3.应用不统一:
--//你可以看到程序在谓词中两种情况的出现.
where FLAG_VARCHAR='1'
或者
where nvl(FLAG_VARCHAR,'0')='0'
where nvl(FLAG_VARCHAR,'0')=:B1
--//这样就必须建立2个索引.实际上如果能使用非空约束,就可以解决这个问题.
SCOTT@book> alter table t modify FLAG_VARCHAR not null;
Table altered.
SCOTT@book> select * from t where nvl(flag_varchar,0)='1';
ID NAME FLAG_NUM F
---------- -------------------- ---------- -
10000 test 1 1
20000 test 1 1
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 9y06mwu7wncxx, child number 0
-------------------------------------
select * from t where nvl(flag_varchar,0)='1'
Plan hash value: 1601196873
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 17 (100)| | 2 |00:00:00.01 | 55 |
|* 1 | TABLE ACCESS FULL| T | 1 | 10000 | 126K| 17 (0)| 00:00:01 | 2 |00:00:00.01 | 55 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAG_VARCHAR"='1')
--//你可以发现非空约束改变了过滤条件,变成了("FLAG_VARCHAR"='1').这样在真正的应用仅仅建立flag_varchar索引就ok了.
SCOTT@book> create index i_t_flag_varchar on t(flag_varchar);
Index created.
--//在flag_varchar字段建立直方图:
SCOTT@book> execute sys.dbms_stats.gather_table_stats ( OwnName => nvl('',user),TabName => 't',Estimate_Percent => NULL,Method_Opt => 'FOR ALL COLUMNS SIZE 1 for columns flag_varchar size 254 ',Cascade => True ,No_Invalidate => false)
PL/SQL procedure successfully completed.
SCOTT@book> select * from t where nvl(flag_varchar,0)='1';
ID NAME FLAG_NUM F
---------- -------------------- ---------- -
10000 test 1 1
20000 test 1 1
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 9y06mwu7wncxx, child number 0
-------------------------------------
select * from t where nvl(flag_varchar,0)='1'
Plan hash value: 932711470
------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 2 (100)| | 2 |00:00:00.01 | 5 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 13 | 2 (0)| 00:00:01 | 2 |00:00:00.01 | 5 |
|* 2 | INDEX RANGE SCAN | I_T_FLAG_VARCHAR | 1 | 1 | | 1 (0)| 00:00:01 | 2 |00:00:00.01 | 3 |
------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("FLAG_VARCHAR"='1')
--//能很好的使用索引.
4.在需要的数据上建立索引:
--//实际上这个需要dba与开发很好的配合,开发要了解oracle的Btree索引不索引全部是NULL的字段.利用这个特性索引仅仅需要的数据.例子.
SCOTT@book> create index if_t_flag_varchar on t(decode(flag_varchar,'1','1'));
Index created.
--//这样仅仅索引flag_varchar='1'的记录.
SCOTT@book> validate index if_t_flag_varchar;
Index analyzed.
SCOTT@book> @ &r/i
HEIGHT BLOCKS NAME LF_ROWS LF_BLKS LF_ROWS_LEN LF_BLK_LEN BR_ROWS BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS
---------- ---------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------- ---------- ----------- --------------- -------------
1 8 IF_T_FLAG_ 2 1 26 7996 0 0 0 0 0 0 1
VARCHAR
MOST_REPEATED_KEY BTREE_SPACE USED_SPACE PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
----------------- ----------- ---------- ---------- ------------ -------------------- ---------- ------------ -------------- ----------------
2 7996 26 1 2 2.5 0 0 0 0
SCOTT@book> validate index i_t_flag_varchar;
Index analyzed.
SCOTT@book> @ &r/i
HEIGHT BLOCKS NAME LF_ROWS LF_BLKS LF_ROWS_LEN LF_BLK_LEN BR_ROWS BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS
---------- ---------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------- ---------- ----------- --------------- -------------
2 48 I_T_FLAG_V 20000 37 260000 7996 36 1 540 8028 0 0 2
ARCHAR
MOST_REPEATED_KEY BTREE_SPACE USED_SPACE PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
----------------- ----------- ---------- ---------- ------------ -------------------- ---------- ------------ -------------- ----------------
19998 303880 260540 86 10000 5002.5 0 0 1 15
--//上下对比索引的BLOCKS,LF_ROWS,LF_BLKS等数值就明白,函数索引很小.这样写语句时写成如下:
SCOTT@book> select * from t where decode(flag_varchar,'1','1')='1';
ID NAME FLAG_NUM F
---------- ---------- ---------- -
10000 test 1 1
20000 test 1 1
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID g0dff6822sga3, child number 0
-------------------------------------
select * from t where decode(flag_varchar,'1','1')='1'
Plan hash value: 4162935806
-------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 2 |00:00:00.01 | 4 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 200 | 2600 | 3 (0)| 00:00:01 | 2 |00:00:00.01 | 4 |
|* 2 | INDEX RANGE SCAN | IF_T_FLAG_VARCHAR | 1 | 2 | | 1 (0)| 00:00:01 | 2 |00:00:00.01 | 2 |
-------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T@SEL$1
2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."SYS_NC00005$"='1')
--//当然这需要开发这样写sql语句.
总结:
--//本来想写nvl与非NULL约束的问题,迁出一堆别的问题,实际上一个好的团队需要相互交流与配合,可惜我们开发人员陷入开发项目的烂泥塘...........
--//提交修改的sql语句遥遥无期,根本没时间修改..
[20170516]nvl与非NULL约束.txt相关推荐
- MySQL非空约束(NOT NULL)
MySQL 非空约束(NOT NULL)可以通过 CREATE TABLE 或 ALTER TABLE 语句实现.在表中某个列的定义后加上关键字 NOT NULL 作为限定词,来约束该列的取值不能为空 ...
- 8、非空约束(NOT NULL)
MySQL 非空约束(NOT NULL)指字段的值不能为空. 对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错.可以通过 CREATE TABLE 或 ALTER TABL ...
- php mysql 非空_MySQL非空约束(NOT NULL)
MySQL 非空约束(NOT NULL)可以通过 CREATE TABLE 或 ALTER TABLE 语句实现.在表中某个列的定义后加上关键字 NOT NULL 作为限定词,来约束该列的取值不能为空 ...
- MySQL 非空约束(NOT NULL)入门
MySQL 非空约束(NOT NULL)指字段的值不能为空.对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错.可以通过 CREATE TABLE 或 ALTER TABLE ...
- mysql建表语句非空约束默认_Navicat mysql 建表字段 默认值 空白、NULL 、empty string的区别...
总结在最后,没啥干货 新建一张用户表CREATE TABLE `user` ( `id` bigint(20) DEFAULT NULL COMMENT '编号', `name` varchar(64 ...
- MySQL约束-自增长约束(auto_increment)、非空约束(not null)、唯一约束(unique)
目录 自增长约束概念 特点 自增字段初始值 delete和truncate在删除后自增列的变化 非空约束概念 删除非空约束 唯一约束概念 文末资源推荐 每文一语 自增长约束概念 在 MySQL 中,当 ...
- 非空约束对数据更新的影响
正如"非空约束"表达的意思,如果对一个字段添加了非空约束,那么我们是不能将这个字段中的值更新为NULL的.T_Debt表的FAmount字段是有非空约束的,如果我们执行下面SQL: ...
- [JavaWeb-MySQL]约束(非空约束,唯一约束,主键约束,外键约束_级联操作)
约束 * 概念: 对表中的数据进行限定,保证数据的正确性.有效性和完整性. * 分类:1. 主键约束:primary key2. 非空约束:not null3. 唯一约束:unique4. 外键约束: ...
- SQL - 创建一个学生表,要求有主键约束和非空约束
SQL - 创建一个学生表,要求有主键约束和非空约束 CREATE TABLE [dbo].[Student] ([ID] [int] NOT NULL,[Name] [nchar](10) NOT ...
- Oracle数据库:约束条件:主键约束、唯一约束、检查约束、非空约束、外键约束、默认值填写
Oracle数据库:约束条件:主键约束.唯一约束.检查约束.非空约束.外键约束.默认值填写 2022找工作是学历.能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开 测开 ...
最新文章
- SCCM 2012系列11 补丁分发下
- 游戏中每日刷新实现思路浅析
- 惊天大谎:让穷人都能上网是Facebook的殖民阴谋?
- 前端一HTML:十二:元素查找过程的详解
- Boost:boost :: bind相等运算符的测试程序
- Window右键添加“用vim打开”
- 反射例子(配置文件)
- DolphinDB配置
- python程序可以在任何安装了解释器_Windows安装多个python解释器
- bzoj 3379: [Usaco2004 Open]Turning in Homework 交作业(区间DP)
- 使用spring的JdbcTemplate进行查询的三种回调方式的比较
- asp.net post任何数据类型流到网站--当当网API传XML文件
- 海康威视ip摄像头通过网线直接连接笔记本电脑使用
- javaweb框架 一些底层实现
- 青花瓷 下载App Store上历史版本的App的ipa的包
- 软件开发外包平台有哪些?收集的一些备用
- 解决Windows 11 NumLock键盘数字灯不亮的问题
- ansys linux运行_ANSYS2020R1 产品Linux平台安装
- java读取加密excel_Java 加密和解密Excel文档
- android蓝牙查看电池容量_Android获取电池电量和电池容量