<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SANDEEP KUMAR</title>
    <description>The latest articles on DEV Community by SANDEEP KUMAR (@sandeep-dos).</description>
    <link>https://dev.to/sandeep-dos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4129746%2F010f76d7-d430-4be6-9493-3854036b4b81.jpg</url>
      <title>DEV Community: SANDEEP KUMAR</title>
      <link>https://dev.to/sandeep-dos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sandeep-dos"/>
    <language>en</language>
    <item>
      <title>Oracle SQL: JSON Functions</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 16:42:54 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-sql-json-functions-53dp</link>
      <guid>https://dev.to/sandeep-dos/oracle-sql-json-functions-53dp</guid>
      <description>&lt;h2&gt;
  
  
  1. Overview of Oracle JSON Functions
&lt;/h2&gt;

&lt;p&gt;Oracle Database provides powerful built-in SQL functions to construct JSON data directly from relational tables. These functions allow developers to transform rows and columns into standard JSON objects and arrays efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Core JSON Functions Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;JSON_OBJECT&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Converts SQL data into a key-value pair formatted as a JSON object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax:&lt;/strong&gt; &lt;code&gt;JSON_OBJECT('key_name' VALUE column_name)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;JSON_OBJECT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ENAME'&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"ENAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KING"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;JSON_OBJECTAGG&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; An aggregate function that groups multiple rows and combines them into a single JSON object document containing multiple key-value pairs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes:&lt;/strong&gt; &lt;strong&gt;IMPORTANT&lt;/strong&gt; — Commonly used when you want to aggregate child rows into a single JSON payload per group or query result set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax:&lt;/strong&gt; &lt;code&gt;JSON_OBJECTAGG(key_expression VALUE value_expression)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;JSON_OBJECTAGG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ENAME'&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"ENAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ENAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BLAKE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ENAME"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CLARK"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;JSON_ARRAY&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Evaluates each expression and returns a JSON array containing the values for each row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax:&lt;/strong&gt; &lt;code&gt;JSON_ARRAY(column_name)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;JSON_ARRAY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"KING"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"BLAKE"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CLARK"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;JSON_ARRAYAGG&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; An aggregate function that converts an entire set of rows/information into a single JSON array containing all values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes:&lt;/strong&gt; &lt;strong&gt;IMPORTANT&lt;/strong&gt; — Ideal for turning a multi-row result set into a single JSON array column in reporting or API development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax:&lt;/strong&gt; &lt;code&gt;JSON_ARRAYAGG(column_name)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;JSON_ARRAYAGG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"KING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"BLAKE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"CLARK"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Reference Table Structure (&lt;code&gt;EMP&lt;/code&gt; Table)
&lt;/h2&gt;

&lt;p&gt;To practice the queries above, use the standard &lt;code&gt;EMP&lt;/code&gt; table structure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Column Name&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Data Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EMPNO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NUMBER(4)&lt;/td&gt;
&lt;td&gt;Employee ID (Primary Key)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR2(10)&lt;/td&gt;
&lt;td&gt;Employee Name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JOB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR2(9)&lt;/td&gt;
&lt;td&gt;Job Role&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SAL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NUMBER(7,2)&lt;/td&gt;
&lt;td&gt;Salary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Interview Preparation &amp;amp; Revision Corner
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Q: What is the main difference between &lt;code&gt;JSON_ARRAY&lt;/code&gt; and &lt;code&gt;JSON_ARRAYAGG&lt;/code&gt;?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; &lt;code&gt;JSON_ARRAY&lt;/code&gt; is a scalar function evaluated per row (producing a separate single-element JSON array for each row), whereas &lt;code&gt;JSON_ARRAYAGG&lt;/code&gt; is an aggregate function that merges multiple rows into &lt;em&gt;one&lt;/em&gt; comprehensive JSON array.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Q: When should you use &lt;code&gt;JSON_OBJECTAGG&lt;/code&gt; instead of regular aggregation functions?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; Use &lt;code&gt;JSON_OBJECTAGG&lt;/code&gt; when you need to serialize relational query results dynamically into standard JSON document formats for web services, REST APIs, or NoSQL migrations directly within Oracle SQL.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>oracle</category>
      <category>oraclesql</category>
      <category>sql</category>
    </item>
    <item>
      <title>Oracle PL/SQL: Regular vs. Pipelined Table Functions</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 16:39:19 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-plsql-regular-vs-pipelined-table-functions-1el9</link>
      <guid>https://dev.to/sandeep-dos/oracle-plsql-regular-vs-pipelined-table-functions-1el9</guid>
      <description>&lt;p&gt;Table functions are specialized PL/SQL functions that return collections of rows and can be queried directly in the &lt;code&gt;FROM&lt;/code&gt; clause of a SQL query as if they were physical database tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Comparison: Regular vs. Pipelined Table Functions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Regular Table Function&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Pipelined Table Function&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory Allocation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (buffers entire collection in PGA memory)&lt;/td&gt;
&lt;td&gt;Low (streams rows iteratively without holding the entire result set in memory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Response Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High Time to First Row (TTFR) — caller waits until processing completes&lt;/td&gt;
&lt;td&gt;Low Time to First Row (TTFR) — caller gets rows immediately as they are generated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Syntax Keyword&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard &lt;code&gt;RETURN &amp;lt;collection_type&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Requires &lt;code&gt;PIPELINED&lt;/code&gt; keyword in function header&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Row Emission&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard assignment into collection&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;PIPE ROW (...)&lt;/code&gt; construct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Return Statement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RETURN collection_variable;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;RETURN;&lt;/code&gt; (empty return statement)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Small data sets, lookup operations&lt;/td&gt;
&lt;td&gt;Large ETL operations, data transformations, real-time streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Database Prerequisites (Object &amp;amp; Table Types)
&lt;/h3&gt;

&lt;p&gt;To query a function using SQL, you must first define named SQL object types at the database level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- 1. Create Row Type Object&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="n"&gt;t_tf_row&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;OBJECT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;

&lt;span class="c1"&gt;-- 2. Create Nested Table Type based on the Row Object&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="n"&gt;t_tf_tab&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="k"&gt;OF&lt;/span&gt; &lt;span class="n"&gt;t_tf_row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation 1: Regular Table Function
&lt;/h3&gt;

&lt;p&gt;Regular table functions fully populate a collection in memory before returning the entire dataset to the caller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;get_tab_tf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;p_rows&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;t_tf_tab&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
    &lt;span class="n"&gt;l_tab&lt;/span&gt; &lt;span class="n"&gt;t_tf_tab&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t_tf_tab&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="n"&gt;p_rows&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
        &lt;span class="n"&gt;l_tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EXTEND&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;l_tab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l_tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;LAST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t_tf_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Description for '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;l_tab&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;get_tab_tf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testing the Regular Function:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_tab_tf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation 2: Pipelined Table Function
&lt;/h3&gt;

&lt;p&gt;Pipelined table functions stream data back to the calling query immediately upon creation using &lt;code&gt;PIPE ROW&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;get_tab_ptf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;p_rows&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;t_tf_tab&lt;/span&gt; &lt;span class="n"&gt;PIPELINED&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="n"&gt;p_rows&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
        &lt;span class="c1"&gt;-- Sends individual row directly to the caller&lt;/span&gt;
        &lt;span class="n"&gt;PIPE&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_tf_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Description for '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Empty RETURN transfers execution control back to the caller&lt;/span&gt;
    &lt;span class="k"&gt;RETURN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;get_tab_ptf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testing the Pipelined Function:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_tab_ptf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Important Technical &amp;amp; Interview Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IMPORTANT:&lt;/strong&gt; In a pipelined function, attempting to execute &lt;code&gt;RETURN collection_name;&lt;/code&gt; results in a compilation error (&lt;code&gt;PLS-00633: RETURN statement in a pipelined function cannot take an expression&lt;/code&gt;). The &lt;code&gt;RETURN;&lt;/code&gt; statement must remain empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; Pipelining substantially reduces overall system memory usage and drastically decreases "Time to First Row" for large datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; Parallel-enabled table functions allow workload splitting across multiple parallel slave processes (&lt;code&gt;PARALLEL_ENABLE&lt;/code&gt; clause), accelerating execution during high-volume processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IMPORTANT:&lt;/strong&gt; The &lt;code&gt;TABLE()&lt;/code&gt; clause wrapper around a table function in SQL queries is mandatory in Oracle 11g and earlier, but became &lt;strong&gt;optional starting from Oracle Database 12c Release 2 (12.2)&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Valid in Oracle 12c R2 and later without the TABLE() operator:&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;get_tab_ptf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interview Questions &amp;amp; Answers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Q1: What is the primary operational difference between a Regular and Pipelined Table Function?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; A regular table function constructs the entire result set in Process Global Area (PGA) memory before returning control to the caller. A pipelined table function sends rows back incrementally as they are processed using &lt;code&gt;PIPE ROW&lt;/code&gt;, saving PGA memory and significantly reducing the time required to display initial results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q2: What happens if you specify a variable inside the &lt;code&gt;RETURN&lt;/code&gt; statement of a pipelined function?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; Oracle generates a PL/SQL compilation error (&lt;code&gt;PLS-00633&lt;/code&gt;). Pipelined table functions pass data back using &lt;code&gt;PIPE ROW(...)&lt;/code&gt;, so the final &lt;code&gt;RETURN;&lt;/code&gt; statement must be blank to signal execution completion.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>oracle</category>
      <category>plsql</category>
    </item>
    <item>
      <title>Oracle PL/SQL: CASE Expression vs. CASE Statement</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 16:37:37 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-plsql-case-expression-vs-case-statement-f06</link>
      <guid>https://dev.to/sandeep-dos/oracle-plsql-case-expression-vs-case-statement-f06</guid>
      <description>&lt;h2&gt;
  
  
  Conditional Control: &lt;code&gt;CASE&lt;/code&gt; Expression vs. &lt;code&gt;CASE&lt;/code&gt; Statement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preserved &amp;amp; Corrected Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CASE Expression&lt;/strong&gt;: Evaluates conditional logic and &lt;strong&gt;returns a single scalar value&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CASE Statement&lt;/strong&gt;: Evaluates conditional logic to &lt;strong&gt;execute procedural actions/statements&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure &amp;amp; Block Inclusion&lt;/strong&gt;: A &lt;code&gt;CASE&lt;/code&gt; statement can form a complete execution control path within a PL/SQL block.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination Syntax&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CASE&lt;/code&gt; Statements end with &lt;strong&gt;&lt;code&gt;END CASE;&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CASE&lt;/code&gt; Expressions end with &lt;strong&gt;&lt;code&gt;END&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Production Code Examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. CASE Expression (Used inside SQL or PL/SQL Assignment)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DECLARE&lt;/span&gt;
   &lt;span class="n"&gt;v_job_id&lt;/span&gt;  &lt;span class="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'IT_PROG'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;v_bonus&lt;/span&gt;   &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
   &lt;span class="c1"&gt;-- CASE Expression returns a value assigned directly to v_bonus&lt;/span&gt;
   &lt;span class="n"&gt;v_bonus&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="n"&gt;v_job_id&lt;/span&gt;
                 &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'IT_PROG'&lt;/span&gt;  &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
                 &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'SA_REP'&lt;/span&gt;   &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;
                 &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
              &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="n"&gt;DBMS_OUTPUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUT_LINE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Bonus: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;v_bonus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. CASE Statement (Procedural Execution Control)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DECLARE&lt;/span&gt;
   &lt;span class="n"&gt;v_job_id&lt;/span&gt; &lt;span class="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'IT_PROG'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
   &lt;span class="c1"&gt;-- CASE Statement executes executable statements based on conditions&lt;/span&gt;
   &lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="n"&gt;v_job_id&lt;/span&gt;
      &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'IT_PROG'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
         &lt;span class="n"&gt;DBMS_OUTPUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUT_LINE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Department: Information Technology'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="c1"&gt;-- Multiple PL/SQL statements allowed here&lt;/span&gt;
      &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'SA_REP'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
         &lt;span class="n"&gt;DBMS_OUTPUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUT_LINE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Department: Sales'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;ELSE&lt;/span&gt;
         &lt;span class="n"&gt;DBMS_OUTPUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUT_LINE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Department: General Support'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- Terminates with END CASE;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interview Notes &amp;amp; Senior Architect Additions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;br&gt;
&lt;strong&gt;Unhandled Cases Trap (&lt;code&gt;CASE_NOT_FOUND&lt;/code&gt;)&lt;/strong&gt;:&lt;br&gt;
In a &lt;strong&gt;PL/SQL &lt;code&gt;CASE&lt;/code&gt; Statement&lt;/strong&gt;, if no &lt;code&gt;WHEN&lt;/code&gt; clause condition matches and no default &lt;code&gt;ELSE&lt;/code&gt; clause is specified, Oracle raises a runtime exception: &lt;strong&gt;&lt;code&gt;ORA-06592: CASE not found while executing CASE statement&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
In a &lt;strong&gt;&lt;code&gt;CASE&lt;/code&gt; Expression&lt;/strong&gt;, if no condition matches and no &lt;code&gt;ELSE&lt;/code&gt; is specified, it silently evaluates to &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>plsql</category>
      <category>oracle</category>
    </item>
    <item>
      <title>Oracle SQL: Pseudo-Columns</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 03:03:55 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-sql-pseudo-columns-381o</link>
      <guid>https://dev.to/sandeep-dos/oracle-sql-pseudo-columns-381o</guid>
      <description>&lt;h2&gt;
  
  
  1. Overview &amp;amp; Core Concepts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition:&lt;/strong&gt; A pseudo-column behaves like a table column, but it is &lt;strong&gt;not actually stored on disk&lt;/strong&gt; in the table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capabilities &amp;amp; Restrictions:&lt;/strong&gt; You can &lt;code&gt;SELECT&lt;/code&gt; from pseudo-columns, but you &lt;strong&gt;cannot&lt;/strong&gt; perform &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt; operations on their values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Common Oracle Pseudo-Columns
&lt;/h3&gt;

&lt;p&gt;Oracle provides several built-in pseudo-columns for administrative, navigational, and sequence-based queries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ROWID&lt;/code&gt;&lt;/strong&gt;: Returns the unique physical address of a row within a database table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ROWNUM&lt;/code&gt;&lt;/strong&gt;: Assigns a sequential integer (starting from 1) to each row returned by a query result set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;NEXTVAL&lt;/code&gt;&lt;/strong&gt;: Retrieves the next available value from a sequence object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CURRVAL&lt;/code&gt;&lt;/strong&gt;: Retrieves the current value of a sequence in the current session.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;COLUMN_VALUE&lt;/code&gt;&lt;/strong&gt;: Used primarily when querying collection types or table functions like &lt;code&gt;XMLTABLE&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;*Example:*SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT column_value
FROM (XMLTABLE('&amp;lt;a&amp;gt;123&amp;lt;/a&amp;gt;'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;ORA_ROWSCN&lt;/code&gt;&lt;/strong&gt;: Returns the conservative upper bound System Change Number (SCN) of the most recent change made to the row. Useful for tracking data staleness or building flashback implementations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;UID&lt;/code&gt; &amp;amp; &lt;code&gt;USER&lt;/code&gt;&lt;/strong&gt;: Returns the unique integer user ID and the username of the current user session.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;*Example Output from Dual Table:*SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT uid, user FROM dual;
&lt;/code&gt;&lt;/pre&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;UID&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;USER&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;HR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;LEVEL&lt;/code&gt;&lt;/strong&gt;: Used with the &lt;code&gt;SELECT ... CONNECT BY&lt;/code&gt; hierarchical query clause to organize flat rows into a tree structure. It returns the current depth level of a node within the hierarchy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Hierarchical Queries &amp;amp; Tree Pseudo-Columns (&lt;code&gt;CONNECT BY&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;When working with hierarchical data (such as an employee-manager reporting line), Oracle provides specialized pseudo-columns to inspect tree structures:&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Hierarchical Query Structure
&lt;/h4&gt;

&lt;p&gt;SQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;empno&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CONNECT_BY_ISLEAF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CONNECT_BY_ISCYCLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SYS_CONNECT_BY_PATH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
    &lt;span class="n"&gt;emp&lt;/span&gt;
&lt;span class="k"&gt;CONNECT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;NOCYCLE&lt;/span&gt;
    &lt;span class="k"&gt;PRIOR&lt;/span&gt; &lt;span class="n"&gt;empno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Explanation of Hierarchical Pseudo-Columns used in Example:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CONNECT_BY_ISLEAF&lt;/code&gt;&lt;/strong&gt;: Returns &lt;code&gt;1&lt;/code&gt; if the current row is a leaf node (has no children in the tree structure), and &lt;code&gt;0&lt;/code&gt; otherwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CONNECT_BY_ISCYCLE&lt;/code&gt;&lt;/strong&gt;: Returns &lt;code&gt;1&lt;/code&gt; if the current row has a child that is an ancestor of itself (a loop in the hierarchy), and &lt;code&gt;0&lt;/code&gt; otherwise. (Requires the &lt;code&gt;NOCYCLE&lt;/code&gt; keyword in the &lt;code&gt;CONNECT BY&lt;/code&gt; clause to avoid infinite loops).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SYS_CONNECT_BY_PATH(column, char)&lt;/code&gt;&lt;/strong&gt;: Returns the path of column values from the root to the current node, separated by the specified character string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Advanced Interview Insights &amp;amp; Frequently Asked Questions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Interviewers heavily test pseudo-columns, especially regarding execution order and limitations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What is the evaluation order of &lt;code&gt;ROWNUM&lt;/code&gt; in a query?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ROWNUM&lt;/code&gt; is assigned &lt;strong&gt;after&lt;/strong&gt; the &lt;code&gt;WHERE&lt;/code&gt; clause is evaluated, but &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;ORDER BY&lt;/code&gt; and &lt;code&gt;GROUP BY&lt;/code&gt; clauses. This is why filtering with &lt;code&gt;ROWNUM &amp;gt; 1&lt;/code&gt; directly will always return zero rows (since row 1 fails the condition, it is discarded, and the next row becomes row 1). To handle pagination safely with &lt;code&gt;ROWNUM&lt;/code&gt;, you must use an inline view or subquery that encapsulates the &lt;code&gt;ORDER BY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can you create your own custom pseudo-columns?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;No, pseudo-columns are system-defined by Oracle. However, virtual columns (introduced in Oracle 11g) allow you to define custom expression-based columns that are stored logically or physically as metadata.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What is the difference between &lt;code&gt;ROWID&lt;/code&gt; and &lt;code&gt;ROWNUM&lt;/code&gt;?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ROWID&lt;/code&gt; is a permanent, unique physical address of a row on disk (stable across transactions until the row is deleted or moved). &lt;code&gt;ROWNUM&lt;/code&gt; is temporary, dynamic, and assigned on-the-fly to rows as they are fetched into the result set during statement execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can you create an index on a &lt;code&gt;ROWNUM&lt;/code&gt; or &lt;code&gt;ROWID&lt;/code&gt; pseudocolumn?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; You cannot index &lt;code&gt;ROWNUM&lt;/code&gt;, but &lt;code&gt;ROWID&lt;/code&gt; acts as the implicit physical primary address of every row and is inherently indexed via the rowid access path. You can, however, create indexes on &lt;strong&gt;Virtual Columns&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What is the purpose of &lt;code&gt;CONNECT_BY_ISCYCLE&lt;/code&gt;?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer:&lt;/strong&gt; When performing hierarchical queries with loops in the data, &lt;code&gt;CONNECT_BY_ISCYCLE&lt;/code&gt; returns &lt;code&gt;1&lt;/code&gt; if the current row has a child that is also its ancestor (a loop), preventing infinite loops when paired with the &lt;code&gt;NOCYCLE&lt;/code&gt; clause.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT NOTES FOR INTERVIEW:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual columns do not consume storage space for data (unlike regular columns), but metadata is stored in the dictionary, and they can be indexed to improve query performance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ROWNUM&lt;/code&gt; is assigned &lt;em&gt;before&lt;/em&gt; any sorting or aggregation happens in a query. If you use &lt;code&gt;ORDER BY&lt;/code&gt; with &lt;code&gt;ROWNUM&lt;/code&gt;, rows are numbered arbitrarily unless wrapped in a subquery.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 Practical Code Example: Hierarchical Queries with Pseudocolumns
&lt;/h2&gt;

&lt;p&gt;SQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;empno&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CONNECT_BY_ISLEAF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CONNECT_BY_ISCYCLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SYS_CONNECT_BY_PATH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hierarchy_path&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;
&lt;span class="k"&gt;CONNECT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;NOCYCLE&lt;/span&gt; &lt;span class="k"&gt;PRIOR&lt;/span&gt; &lt;span class="n"&gt;empno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚖️ Difference: Pseudocolumn vs. Virtual Column
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Pseudocolumn&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Virtual Column&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Table Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not part of the table definition/storage.&lt;/td&gt;
&lt;td&gt;Physically part of the table metadata structure, though values are derived on-the-fly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Value Derivation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generated dynamically by the query engine (e.g., &lt;code&gt;ROWNUM&lt;/code&gt;, &lt;code&gt;LEVEL&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Derived from expressions/other columns of the same table.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Indexing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cannot be indexed directly.&lt;/td&gt;
&lt;td&gt;Can be indexed (including B-tree and function-based indexes).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DML Operations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Selection only (No INSERT/UPDATE/DELETE).&lt;/td&gt;
&lt;td&gt;Selection only; values are managed automatically by the database via expressions (No direct DML on the virtual column).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🏗️ Table Structure Example: Virtual Columns
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;   &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;   &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;SUM&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;-- Virtual Column&lt;/span&gt;
    &lt;span class="n"&gt;Sub&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;-- Virtual Column&lt;/span&gt;
    &lt;span class="n"&gt;Mul&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;-- Virtual Column&lt;/span&gt;
    &lt;span class="n"&gt;Div&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;-- Virtual Column&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>oracle</category>
      <category>oraclesql</category>
      <category>sql</category>
      <category>plsql</category>
    </item>
    <item>
      <title>Oracle SQL: Read-Only Tables</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 02:52:55 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-sql-read-only-tables-4ha6</link>
      <guid>https://dev.to/sandeep-dos/oracle-sql-read-only-tables-4ha6</guid>
      <description>&lt;h3&gt;
  
  
  1. Overview &amp;amp; Core Concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition:&lt;/strong&gt; Oracle allows you to restrict tables to read-only mode, blocking all Data Modification Language (DML) operations (such as &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;) and certain Data Definition Language (DDL) modifications while permitting &lt;code&gt;SELECT&lt;/code&gt; queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Use Cases:&lt;/strong&gt; Protecting reference data, historical archives, compliance data retention, and locking master tables during maintenance or migration windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Methods to Make a Table Read-Only or Restrict Data Modifications
&lt;/h3&gt;

&lt;p&gt;There are multiple approaches in Oracle to enforce read-only behavior on table data, ranging from native table states to permissions, views, and triggers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method 1: Using Native Table Read-Only State (&lt;code&gt;ALTER TABLE ... READ ONLY&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;This is the cleanest, built-in feature introduced in Oracle to directly set a table's state to read-only.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE emp READ ONLY;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reverting to Read-Write:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE emp READ WRITE;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Behavior &amp;amp; Error Handling:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you attempt to insert or update records on a read-only table, Oracle throws a direct error:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL Error:&lt;/strong&gt; &lt;code&gt;ORA-12081: update operation not allowed on table "EMP"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Method 2: Granting Restricted Privileges Across Schemas
&lt;/h4&gt;

&lt;p&gt;You can isolate the master table in a dedicated schema (&lt;code&gt;Schema1&lt;/code&gt; / &lt;code&gt;User-A&lt;/code&gt;) and grant only &lt;code&gt;SELECT&lt;/code&gt; privileges to other users (&lt;code&gt;Schema2&lt;/code&gt; / &lt;code&gt;User-B&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup &amp;amp; Granting Privilege:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Connected as Schema1 (User-A)
GRANT SELECT ON emp TO user_b;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Behavior from User-B's Schema:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Connected as Schema2 (User-B)
INSERT INTO user_a.emp VALUES (..., ...);
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error Output:&lt;/strong&gt; &lt;code&gt;ORA-01031: insufficient privileges&lt;/code&gt; (or general insufficient privileges error).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Method 3 &amp;amp; 4: Creating Views (Standard or Read-Only Views)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You can revoke direct DML access to the base table and expose data strictly via a view.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Starting in Oracle, you can explicitly create a &lt;strong&gt;read-only view&lt;/strong&gt; to block DML directly through the view&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE OR REPLACE VIEW emp_ro_view AS
SELECT * FROM emp
WITH READ ONLY;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Method 5: Using Statement-Level Triggers
&lt;/h4&gt;

&lt;p&gt;You can implement a database trigger to intercept and block any DML transactions at the statement level.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Syntax &amp;amp; Example:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE OR REPLACE TRIGGER tr_block_dml
BEFORE INSERT OR UPDATE OR DELETE ON emp
BEGIN
    RAISE_APPLICATION_ERROR(-20001, 'Table is read-only. DML operations are not allowed.');
END;
/
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Summary Comparison of Read-Only Approaches
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Method&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Cons / Limitations&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;ALTER TABLE READ ONLY&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native, high-performance, dictionary-enforced, prevents accidental DML by table owners/admins without switching mode.&lt;/td&gt;
&lt;td&gt;Requires exclusive table access lock to change state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema Privileges&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clean separation of duties; non-owners cannot write.&lt;/td&gt;
&lt;td&gt;Owner of the schema can still perform DML.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Read-Only Views (&lt;code&gt;WITH READ ONLY&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Granular column/row filtering while keeping base table secured.&lt;/td&gt;
&lt;td&gt;Users with direct table access can still modify the base table.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Triggers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Highly customizable; can include conditional logic (e.g., allow specific users).&lt;/td&gt;
&lt;td&gt;Overhead on every DML statement; can be disabled by users with &lt;code&gt;ALTER TRIGGER&lt;/code&gt; privileges.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Advanced Interview Insights &amp;amp; Frequently Asked Questions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Interviewers frequently probe into the metadata behavior and edge cases of read-only tables.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can you drop or truncate a read-only table?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; DDL operations that modify the table structure or contents (like &lt;code&gt;DROP TABLE&lt;/code&gt; or &lt;code&gt;TRUNCATE TABLE&lt;/code&gt;) are blocked when a table is in &lt;code&gt;READ ONLY&lt;/code&gt; mode. You must first alter the table back to &lt;code&gt;READ WRITE&lt;/code&gt; (&lt;code&gt;ALTER TABLE tab_name READ WRITE;&lt;/code&gt;) before dropping or truncating.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can indexes be created or rebuilt on a read-only table?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Dropping or creating indexes is generally restricted while the table is read-only because it modifies the table's segment metadata.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How can you verify if a table is currently in read-only mode?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;You can query the &lt;code&gt;READ_ONLY&lt;/code&gt; column from data dictionary views like &lt;code&gt;USER_TABLES&lt;/code&gt;, &lt;code&gt;ALL_TABLES&lt;/code&gt;, or &lt;code&gt;DBA_TABLES&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ```
    SELECT table_name, read_only
    FROM user_tables
    WHERE table_name = 'EMP';
    ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>oracle</category>
      <category>oraclesql</category>
      <category>sql</category>
      <category>plsql</category>
    </item>
    <item>
      <title>Oracle SQL: Unused Columns &amp; Virtual Columns</title>
      <dc:creator>SANDEEP KUMAR</dc:creator>
      <pubDate>Wed, 23 Sep 2026 02:50:36 +0000</pubDate>
      <link>https://dev.to/sandeep-dos/oracle-sql-unused-columns-virtual-columns-5b23</link>
      <guid>https://dev.to/sandeep-dos/oracle-sql-unused-columns-virtual-columns-5b23</guid>
      <description>&lt;h2&gt;
  
  
  1. Unused Columns (&lt;code&gt;SET UNUSED&lt;/code&gt;)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview &amp;amp; Concept
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition:&lt;/strong&gt; Marking a column as &lt;strong&gt;&lt;code&gt;UNUSED&lt;/code&gt;&lt;/strong&gt; is a form of &lt;strong&gt;logical deletion&lt;/strong&gt;. The column metadata is hidden, but the physical data remains untouched in the table blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Benefit:&lt;/strong&gt; Unlike a traditional &lt;strong&gt;&lt;code&gt;DROP COLUMN&lt;/code&gt;&lt;/strong&gt; (which locks the table and rewrites every data block to reclaim space immediately), &lt;code&gt;SET UNUSED&lt;/code&gt; is an &lt;strong&gt;instant metadata-only operation&lt;/strong&gt;. This prevents long locks and heavy I/O overhead on large production tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Metadata Hiding:&lt;/strong&gt; Once a column is marked as unused, it cannot be viewed via the &lt;code&gt;DESC&lt;/code&gt; command or standard &lt;code&gt;SELECT *&lt;/code&gt; queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusing Column Names:&lt;/strong&gt; Because Oracle internally renames unused columns in the data dictionary with system-generated names (e.g., &lt;code&gt;SYS_00001_...&lt;/code&gt;), you can immediately create a &lt;strong&gt;new column with the same name&lt;/strong&gt; on the table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reversibility:&lt;/strong&gt; You cannot directly "un-set" an unused column using a simple undo command. To reclaim space permanently, the column must eventually be dropped.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Core SQL Operations &amp;amp; Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;1. Mark a Column as Unused:&lt;/strong&gt;SQL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE cust_details
SET UNUSED (cust_account_number
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;2. View Unused Columns:&lt;/strong&gt;SQL&lt;/p&gt;

&lt;p&gt;To inspect unused columns in a table, query data dictionary views such as &lt;code&gt;DBA_UNUSED_COL_TABS&lt;/code&gt;, &lt;code&gt;USER_UNUSED_COLS&lt;/code&gt;, or use session settings:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SET COLINVISIBLE ON;
DESC cust_details;
*(Alternatively, query `USER_UNUSED_COLS` to see table names and counts of unused columns).*
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;3. Drop All Unused Columns Permanently:&lt;/strong&gt;SQL&lt;/p&gt;

&lt;p&gt;This command physically removes the data and reclaims disk space. It can be resource-intensive on large tables:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE cust_details
DROP UNUSED COLUMNS;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Virtual Columns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview &amp;amp; Concept
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition:&lt;/strong&gt; A virtual column is a &lt;strong&gt;derived column&lt;/strong&gt; defined in a table with an underlying expression that computes values from other physical columns in the same row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage Behavior:&lt;/strong&gt; Virtual columns &lt;strong&gt;do not store data physically on disk&lt;/strong&gt; by default. Instead, the database evaluates the expression dynamically at runtime. &lt;em&gt;(Note: Oracle also supports &lt;code&gt;STORED&lt;/code&gt; virtual columns if persistence is required for indexing or performance).&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rules, Limitations, and Restrictions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DML Restrictions:&lt;/strong&gt; You &lt;strong&gt;cannot&lt;/strong&gt; perform direct DML operations (&lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;) on virtual columns. Their values are managed entirely by the underlying expression.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Table Type Support:&lt;/strong&gt; Virtual columns can only be defined on &lt;strong&gt;Heap-organized tables&lt;/strong&gt;. They are &lt;strong&gt;not supported&lt;/strong&gt; for external tables, Index-Organized Tables (IOT), clustered tables, or temporary tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies:&lt;/strong&gt; A virtual column cannot reference another virtual column; it must reference physical columns within the &lt;strong&gt;same table&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Type:&lt;/strong&gt; The expression for a virtual column must evaluate to a &lt;strong&gt;scalar data type&lt;/strong&gt; only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partitioning:&lt;/strong&gt; Virtual columns can be used as &lt;strong&gt;partition keys&lt;/strong&gt; (e.g., partitioning a table by a year extracted from a date column).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Indexing Virtual Columns
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You can define indexes on virtual columns.&lt;/li&gt;
&lt;li&gt;These indexes behave identically to &lt;strong&gt;Function-Based Indexes&lt;/strong&gt;, allowing the optimizer to pre-calculate and index the results of the virtual column expression for faster retrieval.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SQL Syntax &amp;amp; Example
&lt;/h3&gt;

&lt;p&gt;SQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;   &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;col1&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;col2&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;col3&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;col2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;VIRTUAL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;3. Senior Architect &amp;amp; Interview Masterclass&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What is the difference between &lt;code&gt;DROP COLUMN&lt;/code&gt; and &lt;code&gt;SET UNUSED&lt;/code&gt;?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DROP COLUMN&lt;/code&gt; immediately removes the column definition and physically purges the data from all blocks, which can cause severe locking and performance degradation on large tables.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SET UNUSED&lt;/code&gt; instantly updates the data dictionary metadata, marking the column as dead without touching the physical blocks. Space reclamation is deferred until &lt;code&gt;ALTER TABLE ... DROP UNUSED COLUMNS&lt;/code&gt; is executed manually (often scheduled during maintenance windows)[cite: 5].&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can you add a primary key constraint or unique constraint on a Virtual Column?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Yes! If the underlying expression guarantees uniqueness or non-null behavior, you can add constraints (like &lt;code&gt;NOT NULL&lt;/code&gt; or &lt;code&gt;UNIQUE&lt;/code&gt;) and create indexes on virtual columns, making them extremely powerful for enforcing business rules without duplicating storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What happens to indexes when you mark a column as &lt;code&gt;UNUSED&lt;/code&gt;?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;If the column was part of any indexes, those indexes become unusable/invalid and must be dropped or rebuilt after dropping the unused columns permanently.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>oracle</category>
      <category>oraclesql</category>
      <category>sql</category>
      <category>plsql</category>
    </item>
  </channel>
</rss>
