NOT NULL
imposed on them. Also, the DBMS automatically adds the NOT NULL
to the columns included in the primary key of the table.=
, <
, >
, like
... Even the expression NULL != NULL
will not be true, because it is impossible to unambiguously compare one uncertainty with another. By the way, this expression will not be false either, because when calculating conditions, Oracle is not limited to the
and
states. Due to the presence of an element of uncertainty in the form of NULL, there is another state -
. create procedure test_bool( p_bool boolean ) is begin case when p_bool = true then dbms_output.put_line('TRUE'); when p_bool = false then dbms_output.put_line('FALSE'); else dbms_output.put_line('UNKNOWN'); end case; end test_bool;
set serveroutput on
exec test_bool( null = null ); -- UNKNOWN exec test_bool( null != null ); -- UNKNOWN exec test_bool( null = 'a' ); -- UNKNOWN exec test_bool( null != 'a' ); -- UNKNOWN
IS NULL
and IS NOT NULL
that allow you to make comparisons with NULLs. IS NULL
returns true if the operand is NULL
and false if it is not. select case when null is null then 'YES' else 'NO' end from dual; -- YES select case when 'a' is null then 'YES' else 'NO' end from dual; -- NO
IS NOT NULL
does the opposite: returns true if the value of the operand is different from NULL and false if it is NULL: select case when 'a' is NOT null then 'YES' else 'NO' end from dual; -- YES select case when null is NOT null then 'YES' else 'NO' end from dual; -- NO
DECODE
function that considers two NULLs equivalent to each other. Second, these are composite indices: if the two keys contain empty fields, but all their non-empty fields are equal, then Oracle considers these two keys to be equivalent.DECODE
goes against the system: select decode( null , 1, 'ONE' , null, 'EMPTY' -- , 'DEFAULT' ) from dual;
treated the same as
. For example, if you select rows from a table and the calculation of the condition x = NULL
in the WHERE
gave an
result, then you will not get a single row. However, there is a difference: if the expression ()
returns true, then ()
returns
. The logical operators AND
and OR
also have their own characteristics when processing an unknown state. The specifics in the example below.
: select 1 from dual where dummy = null; --
exec test_bool( not(null = null) ); -- UNKNOWN exec test_bool( not(null != null) ); -- UNKNOWN exec test_bool( not(null = 'a') ); -- UNKNOWN exec test_bool( not(null != 'a') ); -- UNKNOWN
OR
operator: exec test_bool( null or true ); -- TRUE <- !!!!! exec test_bool( null or false ); -- UNKNOWN exec test_bool( null or null ); -- UNKNOWN
AND
operator: exec test_bool( null and true ); -- UNKNOWN exec test_bool( null and false ); -- FALSE <- !!!!! exec test_bool( null and null ); -- UNKNOWN
T
with one numeric column A
and four lines: 1, 2, 3
and NULL
create table t as select column_value a from table(sys.odcinumberlist(1,2,3,null));
PLUSTRACE
). set autotrace on
(1, 2, NULL)
: select * from t where a in(1,2,null); -- [1,2] -- Predicate Information: -- filter("A"=1 OR "A"=2 OR "A"=TO_NUMBER(NULL))
"A"=TO_NUMBER(NULL)
returned the state
. In order to include NULLs in the query result, you will have to specify this explicitly: select * from t where a in(1,2) or a is null; -- [1,2,NULL] -- Predicate Information: -- filter("A" IS NULL OR "A"=1 OR "A"=2)
NOT IN
: select * from t where a not in(1,2,null); -- no rows selected -- Predicate Information: -- filter("A"<>1 AND "A"<>2 AND "A"<>TO_NUMBER(NULL))
A=3
:3 <> 1 AND 3 <> 2 AND 3 <> to_number (NULL) \ / \ / \ / true AND true AND unknown \ / / true AND unknown \ / unknown
NOT IN
is not at all friendly with NULLs: as soon as NULL has fallen into the selection conditions, don't wait for the data. exec test_bool( '' is null ); -- TRUE
select count(*) comments_count, avg(c.vote) avg_vote from habr.comments c join habr.posts p on( c.post_id = p.id ) where lower(p.title) like '%%' and lower(p.title) like '%%'; COMMENTS_COUNT AVG_VOTE --------------- --------- 100500 -100
varchar2
has zero length, then there is nothing to write to the data field, it does not occupy a single byte, and a special value of 0xFF
, indicating the absence of data, is written in the field with length. NULL is presented exactly the same: there is no data field, and 0xFF
is written in the field with length. Developers Orakla could, of course, to separate these two states, but since ancient times they have been led.length('')
will return NULL for you, and not zero, as you obviously expected. Another problem: you can not compare with an empty string. The expression val = ''
returns the state
, since, in fact, equivalent to val = NULL
. select length('') from dual; -- NULL
exec test_bool( 'a' != '' ); -- UNKNOWN
''
(empty string), but do not allow you to save an element with an index of NULL: declare procedure empty_or_null( p_val varchar2 ) is type tt is table of varchar2(1) index by varchar2(10); t tt; begin if p_val is not null then dbms_output.put_line(' '); else -- p_val t(p_val) := 'x'; -- ! , dbms_output.put_line(' '); end if; exception -- p_val . , NULL when others then dbms_output.put_line('NULL'); end; begin empty_or_null( 'qwe' ); -- empty_or_null( '' ); -- empty_or_null( NULL ); -- NULL end;
select decode( null + 10, null, '', '') a from dual; -- select decode( null * 10, null, '', '') a from dual; -- select decode( abs(null), null, '', '') a from dual; -- select decode( sign(null), null, '', '') a from dual; --
select null ||'AA'|| null ||'BB'|| null from dual; -- AABB
COUNT
(and even then not always), ignore null values ​​during calculations. If they did not do this, then the first null that has flown in would have led to the result of the function to an unknown value. Take for example the SUM
function, which needs to sum the series (1, 3, null, 2)
. If it took null values, we would get the following sequence of actions:1 + 3 = 4; 4 + null = null; null + 2 = null
1 + 3 = 4; 4 + null = null; null + 2 = null
. create table agg( id int, n int ); insert into agg values( 1, 1 ); insert into agg values( 2, 3 ); insert into agg values( 3, null ); insert into agg values( 4, 2 ); commit;
select sum(n) from agg; -- 6
COUNT
counting function, if used as a COUNT(*)
or COUNT()
, will take null values ​​into account. However, if it is used in the form COUNT()
, then empty values ​​will be ignored. select count(*) from agg; -- 4 select count(1+1) from agg; -- 4 select count(user) from agg; -- 4
select count(n) from agg; -- 3 select count(id) from agg; -- 4 select count(abs(n)) from agg; -- 3
AVG
. Since it ignores empty values, the result for the N
field will be (1+3+2)/3
, and not (1+3+2)/4
. Perhaps this calculation of the average you do not need. To solve such problems, there is a standard solution - use the NVL
function: select avg(n) from agg; -- (1 + 3 + 2) / 3 = 2 select avg(nvl(n,0)) from agg; -- (1 + 3 + 0 + 2) / 4 = 1.5
, if they are applied to an empty dataset, or if it consists only of NULLs. The exceptions are the REGR_COUNT
and COUNT()
functions intended for counting the number of rows. They in the above cases will return zero. select sum(n) from agg where n is null; -- select avg(n) from agg where n is null; -- select regr_count(n,n) from agg where n is null; -- 0 select count(n) from agg where n is null; -- 0
select sum(n) from agg where 1 = 0; -- select avg(n) from agg where 1 = 0; -- select regr_count(n,n) from agg where 1 = 0; -- 0 select count(n) from agg where 1 = 0; -- 0
GROUPING
and GROUPING_ID
, which have a sharper eye. GROUPING()
will return one if NULL in the dimension column indicates the grouping attribute on this column and zero if it contains a specific value (in particular, NULL). The GROUPING_ID
function is a bit vector from GROUPING
, in this post it is definitely superfluous.GROUPING
, and for details on using the Data Warehousing Guide, chapter 21 . set null [NULL]
with t as ( -- 1 select 'IVAN' customer, 'KEFIR' product, 1 qty from dual union all -- 2 select NULL customer, 'MOLOKO' product, 2 qty from dual union all -- 2 select 'IVAN' customer, 'MOLOKO' product, 2 qty from dual ) select customer cust, grouping(customer) grp_c , product prod, grouping(product) grp_p , sum(qty) qty from t group by cube(customer, product) order by grp_c, grp_p; CUST GRP_C PROD GRP_P QTY ---- ----- ------ ----- ---- [NULL] 0 MOLOKO 0 2 -- 2 IVAN 0 KEFIR 0 1 -- 1 IVAN 0 MOLOKO 0 2 -- 2 IVAN 0 [NULL] 1 3 -- 3 [NULL] 0 [NULL] 1 2 -- 2 [NULL] 1 MOLOKO 0 4 -- 4 [NULL] 1 KEFIR 0 1 -- 1 [NULL] 1 [NULL] 1 5 -- 5
Source: https://habr.com/ru/post/127327/
All Articles