{"id":34,"date":"2014-08-18T15:39:00","date_gmt":"2014-08-18T13:39:00","guid":{"rendered":""},"modified":"2015-11-18T23:18:10","modified_gmt":"2015-11-18T22:18:10","slug":"12c-metadata-only-default-values-for-null-columns","status":"publish","type":"post","link":"https:\/\/ilmarkerm.eu\/blog\/2014\/08\/12c-metadata-only-default-values-for-null-columns\/","title":{"rendered":"12c metadata only default values for NULL columns"},"content":{"rendered":"<p>Before 11g if you added a new column to a table then Oracle had to lock and physically update all rows in the table. Possibly a painful process \ud83d\ude42 11g helped with that a little, giving metadata only default values for NOT NULL columns, so the change was done only in data dictionary, not in the table data.<\/p>\n<pre><code class=\"sql\">SQL&gt; create table default_values (\n  2    id number primary key\n  3  );\n\nTable created.\n\nSQL&gt; insert into default_values values (1);\n\n1 row created.\n\nSQL&gt; alter table default_values add def_w_not_null varchar2(20) default 'THIS IS DEFAULT' not null;\n\nTable altered.\n\nSQL&gt; select * from default_values;\n\n        ID DEF_W_NOT_NULL\n---------- --------------------\n         1 THIS IS DEFAULT\n\nSQL&gt; select * from table(dbms_xplan.display_cursor(null,null,'projection'));\n...\nColumn Projection Information (identified by operation id):\n-----------------------------------------------------------\n\n   1 - \"DEFAULT_VALUES\".\"ID\"[NUMBER,22],\n       NVL(\"DEFAULT_VALUES\".\"DEF_W_NOT_NULL\",'THIS IS DEFAULT')[20]\n...\n<\/code><\/pre>\n<p>So internally Oracle just rewrites the columns with the following expression: <strong>NVL(&#8220;DEFAULT_VALUES&#8221;.&#8221;DEF_W_NOT_NULL&#8221;,&#8217;THIS IS DEFAULT&#8217;)<\/strong>. Makes sense \ud83d\ude42<\/p>\n<p>12c now adds the possibility to add metadata only default value for NULL columns also. Lets see what happens:<\/p>\n<pre><code class=\"sql\">SQL&gt; alter table default_values add def_w_null varchar2(20) default 'THIS IS DEFAULT2';\n\nTable altered.\n\nSQL&gt; select id, def_w_null from default_values;\n\n        ID DEF_W_NULL\n---------- --------------------\n         1 THIS IS DEFAULT2\n\nSQL&gt; select * from table(dbms_xplan.display_cursor(null,null,'projection'));\n...\nColumn Projection Information (identified by operation id):\n-----------------------------------------------------------\n\n   1 - \"ID\"[NUMBER,22], DECODE(TO_CHAR(SYS_OP_VECBIT(\"SYS_NC00003$\",0)),NULL\n       ,NVL(\"DEF_W_NULL\",'THIS IS DEFAULT2'),'0',NVL(\"DEF_W_NULL\",'THIS IS\n       DEFAULT2'),'1',\"DEF_W_NULL\")[20]\n<\/code><\/pre>\n<p>We have much more complex expression now: <strong>DECODE(TO_CHAR(SYS_OP_VECBIT(&#8220;SYS_NC00003$&#8221;,0)),NULL,NVL(&#8220;DEF_W_NULL&#8221;,&#8217;THIS IS DEFAULT2&#8242;),&#8217;0&#8242;,NVL(&#8220;DEF_W_NULL&#8221;,&#8217;THIS IS DEFAULT2&#8242;),&#8217;1&#8242;,&#8221;DEF_W_NULL&#8221;)<\/strong>. And also a new hidden column <strong>SYS_NC00003$<\/strong>. What is in there?<\/p>\n<pre><code class=\"sql\">SQL&gt; select id, DEF_W_NULL, nvl2(SYS_NC00003$,'is not null','is null') is_hidden_col_null, SYS_NC00003$ FROM default_values;\n\n        ID DEF_W_NULL           IS_HIDDEN_C SYS_NC00003$\n---------- -------------------- ----------- --------------------\n         1 THIS IS DEFAULT2     is null\n\nSQL&gt; insert into default_values (id, DEF_W_NULL) values (2, null);\n\n1 row created.\n\nSQL&gt; commit;\n\nCommit complete.\n\nSQL&gt; select id, DEF_W_NULL, nvl2(SYS_NC00003$,'is not null','is null') is_hidden_col_null, SYS_NC00003$ FROM default_values;\n\n        ID DEF_W_NULL           IS_HIDDEN_C SYS_NC00003$\n---------- -------------------- ----------- --------------------\n         1 THIS IS DEFAULT2     is null\n         2                      is not null 01\n\nSQL&gt; insert into default_values (id, DEF_W_NULL) values (3, 'some value');\n\n1 row created.\n\nSQL&gt; select id, DEF_W_NULL, nvl2(SYS_NC00003$,'is not null','is null') is_hidden_col_null, SYS_NC00003$ FROM default_values;\n\n        ID DEF_W_NULL           IS_HIDDEN_C SYS_NC00003$\n---------- -------------------- ----------- --------------------\n         1 THIS IS DEFAULT2     is null\n         2                      is not null 01\n         3 some value           is not null 01\n\nSQL&gt; insert into default_values (id) values (4);\n\n1 row created.\n\nSQL&gt; select id, DEF_W_NULL, nvl2(SYS_NC00003$,'is not null','is null') is_hidden_col_null, SYS_NC00003$ FROM default_values;\n\n        ID DEF_W_NULL           IS_HIDDEN_C SYS_NC00003$\n---------- -------------------- ----------- --------------------\n         1 THIS IS DEFAULT2     is null\n         2                      is not null 01\n         3 some value           is not null 01\n         4 THIS IS DEFAULT2     is not null 01\n<\/code><\/pre>\n<p>This new column seems to set a bit, whether the value in the column &#8220;should be trusted&#8221; or replaced with a default. So, all the rows that existed before the new column was added have NULL is this new column, but all the newly modified rows set a specific bit to 1. Looking at the original expression, then there is also a possibility that this bit is set to 0, maybe this newly added column can contain other &#8220;row status bits&#8221; also?<\/p>\n<pre><code class=\"sql\">DECODE (TO_CHAR (sys_op_vecbit (\"SYS_NC00003$\", 0)),\n    NULL, NVL (\"DEF_W_NULL\", 'THIS IS DEFAULT2'),\n    '0', NVL (\"DEF_W_NULL\", 'THIS IS DEFAULT2'),\n    '1', \"DEF_W_NULL\"\n)\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Before 11g if you added a new column to a table then Oracle had to lock and physically update all rows in the table. Possibly a painful process \ud83d\ude42 11g helped with that a little, giving metadata only default values for NOT NULL columns, so the change was done only in data dictionary, not in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[4],"class_list":["post-34","post","type-post","status-publish","format-standard","hentry","category-blog-entry","tag-oracle"],"_links":{"self":[{"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/posts\/34","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/comments?post=34"}],"version-history":[{"count":3,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/posts\/34\/revisions"}],"predecessor-version":[{"id":154,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/posts\/34\/revisions\/154"}],"wp:attachment":[{"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/media?parent=34"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/categories?post=34"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ilmarkerm.eu\/blog\/wp-json\/wp\/v2\/tags?post=34"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}