Вы находитесь на странице: 1из 19

NULLI SECUNDUS Author JP Vijaykumar Oracle DBA Written May 11th 2009 Modified May 31st 2009 Modified

May 14th 2010 Modified Sep 14th 2011 I love idioms and phrases. One of my favourite phrases is - Nulli secundus (Origin - Latin) adjective, meaning - second to none. I would love to say, null is nulli secundus in Oracle. Why is null so unique? As per rdbms definition, the value of null is unknown Or undefined. Null is not equal to anything. A null is not equal to another null. As such, handling nulls in sql and pl/sql is very tricky. Let us see some of the issues in handling nulls. drop table null_jp; create table null_jp (empno number, ename varchar2(20),sal number, comm number) tablespace users; truncate table null_jp; insert into null_jp(empno,ename,sal,comm) values(101,'JOSE',1000,''); --No value is inserted. An explicit null . insert into null_jp(empno,ename,sal,comm) values(102,'JOJO',null,20); --A null is inserted. An explicit null. insert into null_jp(empno ,sal,comm) values(103, 1100,90); --An implicit null inserted, by omitting value for ename column. insert into null_jp( ename,sal,comm) values( 'JOJO',1200,40); --An implicit null inserted, by omitting value for empno column. commit; SQL> select * from null_jp; EMPNO ---------101 102 103 ENAME SAL COMM -------------------- ---------- ---------JOSE 1000 JOJO 20 1100 90 JOJO 1200 40

4 rows selected. SQL> select count(*) from null_jp; COUNT(*) ---------4 1 row selected.

SQL> select count(empno) from null_jp; COUNT(EMPNO) -----------3 1 row selected. The table null_jp is having 4 rows. But a count on empno column from the table displays only 3 rows. Oracle could not count null values in the empno column. By using a nvl function on the empno column, we can derive the expected result. SQL> select count(nvl(empno,0)) from null_jp; COUNT(NVL(EMPNO,0)) ------------------4 1 row selected. select count(ename) from null_jp; COUNT(ENAME) -----------------3 1 row selected. The table null_jp is having 4 rows. Again a count on ename column from the table displays only 3 rows. Oracle could not count the null value in the empno column. To count the null value in the ename column , I used the nvl function on the ena me column. select count(nvl(ename,'X')) from null_jp; COUNT(NVL(ENAME,'X')) --------------------4 1 row selected. SQL> select ename from null_jp; ENAME -------------------JOSE JOJO JOJO 4 rows selected. A null is not equal to anything nor equql to another null.

SQL> select ename from null_jp where ename= (nvl(ename,'')); ENAME -------------------JOSE JOJO JOJO 3 rows selected. SQL> select ename from null_jp where (nvl(ename,'')) = (nvl(ename,'')); ENAME -------------------JOSE JOJO JOJO 3 rows selected. How to select the records from the table, that have null ename value? SQL> select ename from null_jp where ename = ''; no rows selected SQL> select ename from null_jp where ename = null; no rows selected Only "IS NULL" and "IS NOT NULL" can be used to check for values that are null or not null. SQL> select ename from null_jp where ename is null; ENAME -------------------1 row selected. SQL> select ename from null_jp where ename is not null; ENAME -------------------JOSE JOJO JOJO 3 rows selected. Using this construct, I can equate a null to another null. SQL> select ename from null_jp where (nvl(ename,'ZZZ')) = (nvl(ename,'ZZZ')); ENAME --------------------

JOSE JOJO JOJO 4 rows selected. Let us find the records from our table, whose sum of sal + comm is greater than or equal to 20. SQL> select * from null_jp where (sal + comm ) >= 20; EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------103 1100 90 JOJO 1200 40 2 rows selected.

From my observation, all 4 rows from null_jp table satisfy the where condition. Since two rows are having null values in the sal and comm columnS, these two row s were not computed by Oracle to evaluate in the where condition of the query. Using nvl function on sal and comm columns, this can be resolved. SQL> select * from null_jp where (nvl(sal,0) + nvl(comm,0) ) >= 20; EMPNO ---------101 102 103 ENAME SAL COMM -------------------- ---------- ---------JOSE 1000 JOJO 20 1100 90 JOJO 1200 40

4 rows selected. These queries find only the rows having null ename values in the table null_jp. SQL> select * from null_jp where ename is null; EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------103 1100 90 1 row selected. SQL> select * from null_jp where nvl(ename,'xyz') = 'xyz'; EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------103 1100 90 1 row selected.

Here is an unique query. If no values is supplied for ename column, the the quer y returns all records in the table with NON NULL values for ename column. And if a value is supplied for ename column, the query returns that specific record from null_jp table which matches the supplied ename value. SQL> select * from null_jp where ename = nvl(upper('&ename'),ename); Enter value for ename: old 1: select * from null_jp where ename = nvl(upper('&ename'),ename) new 1: select * from null_jp where ename = nvl(upper(''),ename) EMPNO ---------101 102 ENAME SAL COMM -------------------- ---------- ---------JOSE 1000 JOJO 20 JOJO 1200 40

3 rows selected. SQL> / Enter value for ename: jose old 1: select * from null_jp where ename = nvl(upper('&ename'),ename) new 1: select * from null_jp where ename = nvl(upper('jose'),ename) EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------101 JOSE 1000 1 row selected.

In either case Oracle returns records having NON NULL ename values. How to get all the rows from the null_jp table using a where condition on ename column, wherein the ename is either null or not null(I want to get all the 4 rows from m y table): SQL> select * from null_jp where nvl(ename,'null') = decode(nvl(ename,null),null ,'null',ename); EMPNO ---------101 102 103 ENAME SAL COMM -------------------- ---------- ---------JOSE 1000 JOJO 20 1100 90 JOJO 1200 40

4 rows selected. The same result can be obtained from the null_jp table with the following querie s also: select * from null_jp where ename is null

union select * from null_jp where ename is not null; select * from null_jp where (ename is null or ename is not null); select ename from null_jp where (nvl(ename,'ZZZ')) = (nvl(ename,'ZZZ'));

Some often overlooked errors, while handling nulls in pl/sql programming. This cursor loop displays all the ename values with a counter number, incremented after each iteration in the loop. set serverout on size 100000 declare v_num number; begin for c1 in (select ename from null_jp) loop v_num:=v_num+1; dbms_output.put_line(v_num ' ' c1.ename); end loop; end; / JOSE JOJO JOJO PL/SQL procedure successfully completed. Here the v_num value is not displayed in the output. Oracle could not increment the v_num value inside the loop, as v_num is null. This issue can be fixed in either way: declare v_num number:=0; begin for c1 in (select ename from null_jp) loop v_num:=v_num+1; dbms_output.put_line(v_num ' ' c1.ename); end loop; end; / By initializing the v_num variable at the begining of the loop. declare v_num number; begin for c1 in (select ename from null_jp) loop v_num:=nvl(v_num,0)+1; dbms_output.put_line(v_num ' ' c1.ename); end loop; end; /

Or by using the nvl function on the v_num variable inside the loop. Now I could display the output from my pl/sql script as expected. 1 JOSE 2 JOJO 3 4 JOJO PL/SQL procedure successfully completed. The following script displays, all similar enames in the output with a message. For some reason the c1.ename cursor variable values are not displayed in my the output. declare v_num number:=0; v_dup varchar2(20); begin for c1 in (select ename from null_jp order by ename) loop v_num:=v_num+1; dbms_output.put_line(v_num); if ( v_dup = c1.ename) then dbms_output.put_line(v_num ' ' c1.ename ' duplicate ename found'); elsif ( v_dup <> c1.ename) then v_dup:=c1.ename; dbms_output.put_line(v_num ' ' c1.ename); end if; end loop; end; / 1 2 3 4 Oracle could not compare the ename values with v_dup cursor variable, which is n ull. As such the duplicates of the ename values are not displayed in the cursor loop output. This issue can be fixed in either way: declare v_num number:=0; v_dup varchar2(20):='x'; begin for c1 in (select ename from null_jp order by ename) loop v_num:=v_num+1; dbms_output.put_line(v_num); if ( v_dup = c1.ename) then dbms_output.put_line(v_num ' ' c1.ename ' duplicate ename found'); elsif ( v_dup <> c1.ename) then v_dup:=c1.ename; dbms_output.put_line(v_num ' ' c1.ename); end if;

end loop; end; / By initialized the v_dup variable before the begining of the loop. declare v_num number:=0; v_dup varchar2(20); begin for c1 in (select ename from null_jp order by ename) loop v_num:=v_num+1; dbms_output.put_line(v_num); if ( nvl(v_dup,'x') = c1.ename) then dbms_output.put_line(v_num ' ' c1.ename ' duplicate ename found'); elsif ( nvl(v_dup,'x') <> c1.ename) then v_dup:=c1.ename; dbms_output.put_line(v_num ' ' c1.ename); end if; end loop; end; / Or by using a nvl function on the v_dup variable inside the loop, the issue can be fixed. 1 1 JOJO 2 2 JOJO duplicate ename found 3 3 JOSE 4 After initializing the v_dup string in the script, the script displayed the expected results. ******************SOME COMPLEXITIES IN UNDERSTANDING NULLS********************** **** drop table " "; create table " " (empno number, ename varchar2(20),sal number, comm number) tablespace users; SQL> desc " " Name Null? ----------------------------------------- -------EMPNO ENAME SAL COMM Type ---------------------------NUMBER VARCHAR2(20) NUMBER

Here I created a tables without a name, in fact the table's name is two blank sp aces enclosed in double codes. Again the table name is not null. truncate table " ";

insert into " "(empno,ename,sal,comm) values(101,'JOSE',1000,''); --No value is inserted. An explicit null . insert into " "(empno,ename,sal,comm) values(102,'JOJO',null,20); --A null is inserted. An explicit null. insert into " "(empno ,sal,comm) values(103, 1100,90); --An implicit null inserted, by omitting value for ename column. insert into " "( ename,sal,comm) values( 'JOJO',1200,40); --An implicit null inserted, by omitting value for empno column. insert into " "(empno,ename,sal,comm) values(105,' ',2000,10); --A string value of 4 blank spaces is in serted, not null. insert into " "(empno,ename,sal,comm) values(106,'NULL',1100,90); --A string value of NULL is inserted, no t null. commit; SQL> select * from " "; EMPNO ---------101 102 103 ENAME SAL COMM -------------------- ---------- ---------JOSE 1000 JOJO 20 1100 90 JOJO 1200 40 105 2000 10 106 NULL 1100 90

6 rows selected.

select * from " " where ename='NULL'; EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------106 NULL 1100 90 1 row selected. I select a record from " " table with ename that contains a string value of 'NU LL'. select * from " " where ename=NULL; no rows selected How can I select the rows from the table, where the ename is null? SQL> select * from " " where ename is NULL; EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------103 1100 90 1 row selected.

This record from " " table is having null ename value. The following record from " " table is not having null ename value. Instead a string value of four blank spaces was inserted for ename value. select * from " " where ename=' ';

EMPNO ENAME SAL COMM ---------- -------------------- ---------- ---------105 2000 10 1 row selected. SQL> create table " " (empno number, ename varchar2(20),sal number, comm number ) tablespace users; 2 create table " " (empno number, ename varchar2(20),sal number, comm number) * ERROR at line 1: ORA-00955: name is already used by an existing object Oracle did not allow me to create another table with two blank spaces as the tab le's name. SQL> create table " " (empno number, ename varchar2(20),sal number, comm number) tablespace users; 2 Table created. I could create a table with one blank space as my table's name. SQL> desc " " Name Null? ----------------------------------------- -------EMPNO ENAME SAL COMM Type ---------------------------NUMBER VARCHAR2(20) NUMBER NUMBER

If you are creating tables with names containing only blank spaces, then you have to remember the number of blank spaces used for your table name, so as to access and manipulate the tables. For example, I created two tables, one with one blank space and the second with two blank spaces. Let us see, what we make out for these tab les from the dba_objects view: SQL> select object_name from dba_objects where object_type='TABLE' and created > sysdate - 10/1440; OBJECT_NAME --------------------------------------------------------------------------------

2 rows selected.

Getting the table_names from the data dictionary, that had no visible names is not a straight forward case. Let us find the tables in the database with blank spaces and how many blank spaces are there in each of our tables' names. Oracle treats the blank spaces a s names.

SQL> column object_name format a10 SQL> select object_name, length(object_name) from dba_objects where object_type='TABLE' and created > sysdate - 10/1440; OBJECT_NAM LENGTH(OBJECT_NAME) ---------- ------------------1 2 2 rows selected. SQL> drop table " "; Table dropped. SQL> drop table " "; Table dropped. SQL> column object_name format a30 SQL> select object_name, length(object_name) from dba_objects where object_type='TABLE' and created > sysdate - 10/1440; OBJECT_NAME LENGTH(OBJECT_NAME) ------------------------------ ------------------BIN$bCiN9VXIFJ7gRAAXpHae/Q==$0 30 BIN$bCiN9VXJFJ7gRAAXpHae/Q==$0 30 2 rows selected. SQL> purge dba_recyclebin; DBA Recyclebin purged. SQL> select object_name, length(object_name) from dba_objects where object_type='TABLE' and created > sysdate - 10/1440; no rows selected From the foregoing, blank spaces are not treated in Oracle as null. Only when no value is specified for a table's column, then Oracle treats it as n ull. *****************************ADDED 05-14-2010******************************** **** An nvl function can be used on a table's column values and on the whole sql queries also. SQL> create table temp_jp(empno number, ename varchar2(20), 2 hiredate date, sal number);

Table created. SQL> TRUNCATE TABLE temp_jp; Table truncated. SQL> insert into temp_jp(empno,ename,hiredate,sal) values 2 (1,'RAMAMOHAN',to_date('05-14-2010','mm-dd-yyyy'),100); 1 row created. SQL> insert into temp_jp(empno,ename,hiredate) values 2 (2,'VEEKSHA',to_date('05-14-2010','mm-dd-yyyy')); 1 row created. SQL> commit; Commit complete. SQL> select * from temp_jp; EMPNO ---------1 2 ENAME -------------------RAMAMOHAN VEEKSHA HIREDATE SAL --------- ---------14-MAY-10 100 14-MAY-10

SQL> select nvl(sal,0) from temp_jp where empno=2; NVL(SAL,0) ---------0 SQL> select * from temp_jp where empno=3; no rows selected SQL> select nvl((select ename from temp_jp where empno=3),0) from dual; NVL((SELECTENAMEFROM -------------------0 SQL> select case when empno=0 then 'FALSE' when empno>0 then 'TRUE' end status from (select nvl((select empno from temp_jp where empno=2),0) empno from dua l); 2 3 STATU ----TRUE SQL> select case when empno=0 then 'FALSE' when empno>0 then 'TRUE' end status from (select nvl((select empno from temp_jp where empno=3),0) empno from dua l); 2 3 STATU

----FALSE **************************ADDED 09-14-2011************************************** **** null had no data type. By default null is string(character) varchar2 data type. create or replace view null_view as select null col1 from dual; View created. desc null_view Name Null? Type ----------------------------------------- -------- ---------------------------COL1 VARCHAR2 select * from null_view; C select * from null_view where col1 is null; C create or replace view null_view as select 'null' col1 from dual; View created. desc null_view Name Null? Type ----------------------------------------- -------- ---------------------------COL1 CHAR(4) select * from null_view; COL1 ---null select * from null_view where col1 is null; no rows selected select * from null_view where col1 =''; no rows selected select * from null_view where col1 ='null'; COL1 ---null In the above example, the null_view is created NOT WITH null value, but with a string value of 'null'.

----------------------------------------------------------------------------------Null is very handy to substitute missing columns, while using UNION /UNION ALL/M INUS clauses. select 'x' from dual union select 1 from dual; select 'x' from dual * ERROR at line 1: ORA-01790: expression must have same datatype as corresponding expression select null,'x' from dual union select 1,'null' from dual; NULL 'X' ---------- -------------------------------1 null x select null,'x' from dual union select 1,null from dual; NULL 'X' ---------- -------------------------------1 x select sysdate,'x' from dual union select 'null' from dual; select sysdate,'x' from dual * ERROR at line 1: ORA-01789: query block has incorrect number of result columns

select sysdate,'x' from dual union select null ,'null' from dual; SYSDATE 'X' --------- -------------------------------14-SEP-11 x null select sysdate,'x' from dual union select null ,null from dual; SYSDATE 'X'

--------- -------------------------------14-SEP-11 x ----------------------------------------------------------------------------------Handling nulls in pl/sql: create table jp.temp_jp1(col1 number) tablespace users; create table jp.temp_jp2(col1 number,col2 blob) tablespace users; create table jp.temp_jp3(col1 number) tablespace users; set serverout on size 1000000 timing on declare begin for i in 1..1000000 loop begin insert into jp.temp_jp1 values(i); insert into jp.temp_jp2 values(i,empty_blob()); insert into jp.temp_jp3 values(i); exception when others then dbms_output.put_line(sqlerrm); end; end loop; commit; end; / create index jp.temp_jp3_idx01 on jp.temp_jp3(col1) tablespace users; select segment_type,round(sum(bytes)/1024/1024,2) segment_size_mg from dba_segments where owner='JP' group by segment_type order by 1; SEGMENT_TYPE SEGMENT_SIZE ------------------ -----------INDEX 16 LOBINDEX .06 LOBSEGMENT .06 TABLE 78 column segment_name format a30 select segment_name,segment_type,round(sum(bytes)/1024/1024,2) segment_size_mg from dba_segments where owner='JP' group by segment_name,segment_type order by 1 ; SEGMENT_NAME -----------------------------SYS_IL0000179461C00002$$ SYS_LOB0000179461C00002$$ TEMP_JP1 TEMP_JP2 TEMP_JP3 TEMP_JP3_IDX01 6 rows selected. Now I want to write a pl/sql procedure to process the objects and their size and SEGMENT_TYPE SEGMENT_SIZE_MG ------------------ --------------LOBINDEX .06 LOBSEGMENT .06 TABLE 13 TABLE 52 TABLE 13 INDEX 16

also tatal size by object_type. PROCEDURE 01 -----------set serverout on size 1000000 timing on linesize 200 declare v_owner varchar2(10); v_tsize number; v_isize number; v_lsize number; v_ttsize number:=0; v_tisize number:=0; v_tlsize number:=0; begin dbms_output.put_line('TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB'); for c1 in (select owner,table_name,num_rows from dba_tables where owner='JP' order by 2 ) loop begin v_owner:=c1.owner; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,table_name from dba_tables where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''' ) ' into v_tsize; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,index_name from dba_indexes where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''') ' into v_isize; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,segment_name from dba_lobs where owner = ''' c1.owner ''' and table_name = ''' c1.table_name ''' )' into v_lsize; dbms_output.put_line(c1.table_name ' :' v_tsize ':' v_isize ' :' v_lsize); v_ttsize:=v_ttsize + v_tsize; v_tisize:=v_tisize + v_isize; v_tlsize:=v_tlsize + v_lsize; exception when others then dbms_output.put_line(c1.table_name ',' sqlerrm); end ; end loop; dbms_output.put_line(v_owner ' :' v_ttsize ' :' v_tisize ':' v_tlsize); end; / TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB TEMP_JP1 :13: : TEMP_JP2 :52:0 :0 TEMP_JP3 :13:18 : JP :78 :: PL/SQL procedure successfully completed. Elapsed: 00:00:13.26

I am not getting the display for index segments and blob segments in my procedur e's output. I modified the above procedure a little bit to debug the issue. PROCEDURE 02 -----------set serverout on size 1000000 timing on linesize 200 declare v_owner varchar2(10); v_tsize number; v_isize number; v_lsize number; v_ttsize number:=0; v_tisize number:=0; v_tlsize number:=0; begin dbms_output.put_line('TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB'); for c1 in (select owner,table_name,num_rows from dba_tables where owner='JP' order by 2 ) loop begin v_owner:=c1.owner; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,table_name from dba_tables where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''' ) ' into v_tsize; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,index_name from dba_indexes where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''') ' into v_isize; execute immediate 'select round(sum(bytes)/1024/1024) from dba_segments where (o wner,segment_name) in (select owner,segment_name from dba_lobs where owner = ''' c1.owner ''' and table_name = ''' c1.table_name ''' )' into v_lsize; dbms_output.put_line(c1.table_name ' :' v_tsize ':' v_isize ' :' v_lsize ':' v_tisize); v_ttsize:=v_ttsize + v_tsize; v_tisize:=v_tisize + v_isize; v_tlsize:=v_tlsize + v_lsize; exception when others then dbms_output.put_line(c1.table_name ',' sqlerrm); end ; end loop; dbms_output.put_line(v_owner ' :' v_ttsize ' :' v_tisize ':' v_tlsize); end; / TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB TEMP_JP1 :13: ::0 TEMP_JP2 :52:0 :0: TEMP_JP3 :13:18 :: JP :78 :: PL/SQL procedure successfully completed. Elapsed: 00:00:05.76

From the above output, the total_index_size is becoming null at some point. The problem is solved, by handling the null values in the procedure. I need to handle the null values in the procedure's run properly. PROCEDURE 03 -----------set serverout on size 1000000 timing on linesize 200 declare v_owner varchar2(10); v_tsize number; v_isize number; v_lsize number; v_ttsize number:=0; v_tisize number:=0; v_tlsize number:=0; begin dbms_output.put_line('TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB'); for c1 in (select owner,table_name,num_rows from dba_tables where owner='JP' order by 2 ) loop begin v_owner:=c1.owner; execute immediate 'select nvl(round(sum(bytes)/1024/1024),0) from dba_segments w here (owner,segment_name) in (select owner,table_name from dba_tables where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''' ) ' into v_tsize; execute immediate 'select nvl(round(sum(bytes)/1024/1024),0) from dba_segments w here (owner,segment_name) in (select owner,index_name from dba_indexes where owner=''' c1.owner ''' and table_name = ''' c1.table_name ''') ' into v_isize; execute immediate 'select nvl(round(sum(bytes)/1024/1024),0) from dba_segments w here (owner,segment_name) in (select owner,segment_name from dba_lobs where owner = ''' c1.owner ''' and table_name = ''' c1.table_name ''' )' into v_lsize; dbms_output.put_line(c1.table_name ' :' v_tsize ':' v_isize ' :' v_lsize ':' v_tisize); v_ttsize:=v_ttsize + v_tsize; v_tisize:=v_tisize + v_isize; v_tlsize:=v_tlsize + v_lsize; exception when others then dbms_output.put_line(c1.table_name ',' sqlerrm); end ; end loop; dbms_output.put_line(v_owner ' :' v_ttsize ' :' v_tisize ':' v_tlsize); end; / TABLE_NAME,NUM_ROWS,SEGMENT_NAME,SEGMENT_TYPE,SIZE_MB TEMP_JP1 :13:0 :0:0 TEMP_JP2 :52:0 :0:0 TEMP_JP3 :13:18 :0:0 JP :78 :18:0

PL/SQL procedure successfully completed. Elapsed: 00:00:12.47 ----------------------------------------------------------------------------------REFERENCE: http://www.databasejournal.com/scripts/article.php/3828731/Nulli-Secundus.htm http://dbaforums.org/oracle/index.php?showtopic=7714 --NULL DATA TYPE http://orafaq.com/wiki/NULL http://dictionary.reverso.net/english-definitions/nulli%20secundus http://www.psoug.org/reference/null.html http://www.databasedesign-resource.com/null-values-in-a-database.html http://www.oracle-base.com/articles/misc/NullRelatedFunctions.php http://www.morganslibrary.org/reference/tuning.html#np

Вам также может понравиться