rownum in Oracle cannot use greater than > problem

Reference: http://www.cnblogs.com/java0819/archive/2011/08/03/2146205.html

1. Explanation of rownum

 

   Regarding the rownum problem of Oracle, many sources say that the ">, >=, =, between...and" operators in SQL statements are not supported, and only the following operator symbols "<, <=, !=" can be used,

 

   It does not mean that SQL syntax errors will be prompted when using ">, >=, =, between..and", but it is often that a record cannot be found, and seemingly inexplicable results will appear.

 

   In fact, as long as you understand the meaning of this rownum pseudocolumn, you shouldn't be surprised.

 

   Although rowid and rownum are both called pseudo-columns, they exist in different ways:

 

   The rowid exists physically and represents the unique location ID recorded in the tablespace, which is unique in the DB. As long as the record has not been moved, the rowid is unchanged.

 

   Compared with the table, rowid is like a general column in the table, so there will be no inexplicable results of rownum based on rowid.

 

   Also note: rownum cannot be prefixed with the name of any base table.

 

   For the following SQL statement

 

   SQL>select rownum,id,age,name from loaddata where rownum > 2;

 

    ROWNUM ID     AGE NAME

    ------- ------ --- ------

 

    rownum>2, no records were queried.

 

    Because rownum always starts from 1, if the first row is not satisfied and removed, the rownum of the second row becomes 1 again. And so on, so there is never a record that meets the condition.

 

    It can be understood this way: rownum is a sequence, which is the order in which the Oracle database reads data from the data file or buffer.

 

    It gets the rownum value of 1 for the first record and 2 for the second. And so on.

 

    When using the conditions of ">, >=, =, between...and", the rownum of the first record obtained from the buffer or data file is 1, which does not meet the conditions of the SQL statement and will be deleted, and then Remove the bar.

 

    The rownum of the next item will still be 1, and it will be deleted, and so on, and there will be no data.

 

 

2. Analysis and explanation of several phenomena in the use of rownum

  

    With the above concept of rownum established from different aspects, the following are some phenomena of using rownum:

 

    (1) select rownum,id,age,name from loaddata where rownum != 10 Why is the first 9 pieces of data returned?

     Why does it return the same result set as select rownum,id,age,name from loaddata where rownum < 10?

 

     Because after the result set is queried and the ninth record is displayed, the following records are all != 10 or >= 10, so only the first nine records are displayed.

 

     It can also be understood in this way, after the rownum is 9, the rownum of the fetched record is 10, because the condition is !=10, so delete it. Then take the next one, its rownum is 10 again, also delete. And so on.

 

     So only the first 9 records will be displayed.

 

 

    (2) When rownum > 1, no record can be found, but rownum > 0 or rownum >= 1 always displays all records.

 

     This is because rownum is added after the query result set, and it always starts from 1.

 

 

    (3) Why between 1 and 10 or between 0 and 10 can get the result, but between 2 and 10 can't get the result.

 

     The reason is the same as above: because rownum always starts from 1.

 

 

     From the above, it is wrong to discard the rownum = 1 record at any time. It is indispensable in the result set.

 

     Without rownum=1, it cannot exist like a castle in the sky. Therefore, the rownum condition should include 1.

 

 

Three, some examples of the actual use of rownum:

 

     -----------

     --sql table build script

 

     create table LOADDATA

     (

         ID   VARCHAR2(50),

         AGE  VARCHAR2(50),

         NAME VARCHAR2(50)

     );

     -----------

 

    (1) rownum for the query condition of "equal to a value"

 

     If you want to find the information of the first record in the loaddata table, you can use rownum=1 as a condition.

 

     However, if you want to find the information of the second record in the loaddata table, you can't find the data by using rownum=2.

 

     Because rownum starts from "1".

 

     The natural numbers above "1" are considered to be false conditions when rownum is equal to the judgment, so rownum = n (natural numbers with n>1) cannot be found.

 

 

      select rownum,id,age,name 

      from loaddata 

      where rownum = 1; -- can be used to limit the number of records returned to ensure no errors, such as: implicit cursor.

 

 

    SQL>select rownum,id,age,name from loaddata where rownum = 1;

 

    ROWNUM ID     AGE NAME

    ------- ------ --- ------

         1 200001 22   AAA

 

 

    SQL>select rownum,id,age,name from loaddata where rownum = 2;

 

    ROWNUM ID     AGE NAME

    ------- ------ --- ------

 

 

   Note: SQL>select rownum,id,age,name from loaddata where rownum != 3; --The first 2 records are returned.

 

     ROWNUM ID     AGE NAME

    ------- ------ --- ------

         1 200001 22   AAA

         2 200002 22 BBB

 

 

  (2) rownum for query conditions greater than a certain value

 

    If you want to find records after the second row, you cannot find records when rownum>2 is used.

 

    The reason is that because rownum is a pseudo-column that always starts from 1, Oracle thinks that the condition of rownum>n (a natural number of n>1) still does not hold, so no records can be found.

 

    SQL>select rownum,id,age,name from loaddata where rownum > 2;

 

    ROWNUM ID     AGE NAME

    ------- ------ --- ------

 

 

    How can I find the records after the second line?

 

    This can be solved using the following subquery method.

 

    Note that rownum in the subquery must have an alias, otherwise the record will still not be found, because rownum is not a column of a table.

 

    If you don't have an alias, you can't know whether rownum is a column in the subquery or a column in the main query.

 

 

     SQL>select rownum,id,age,name from(select rownum no ,id,age,name from loaddata) where no > 2;

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         3 200003 22 CCC

         4 200004 22   DDD

         5 200005 22   EEE

         6 200006 22   AAA

 

 

     SQL>select * from(select rownum,id,age,name from loaddata) where rownum > 2;

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

 

 

 

    (3) rownum for query conditions less than a certain value

 

     If you want to find the records before the third record, you can get two records when using rownum<3.

 

     Obviously, the condition of rownum for rownum<n ((n>1 natural number) is considered to be true, so the record can be found.

 

     SQL> select rownum,id,age,name from loaddata where rownum < 3;

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         1 200001 22   AAA

         2 200002 22 BBB

 

 

     To sum up the above situation:

 

     It may sometimes be necessary to query the data of rownum in a certain interval. It can be seen from the above that rownum considers the query condition less than a certain value to be true.

 

     rownum is directly considered false for query conditions greater than a certain value, but it can be indirectly considered to be true, then a subquery must be used.

 

     For example, if you want to query the data of rownum between the second row and the third row, including the data in the second row and the third row, you can only write the following statement, and let it return the rows of records less than or equal to three,

 

     Then, in the main query, determine the record row whose "alias column" of the new rownum is greater than or equal to two. But such operations will affect the retrieval speed in large datasets.

 

 

     SQL>select * from (select rownum no,id,age,name from loaddata where rownum <= 3 ) where no >= 2; --must be small inside and big outside

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         2 200002 22 BBB

         3 200003 22 CCC

 

 

     It can also be achieved this way:

 

     SQL>select rownum,id,age,name from loaddata where rownum < 4

         minus

         select rownum,id,age,name from loaddata where rownum < 2

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         2 200002 22 BBB

         3 200003 22 CCC

 

 

 

    (4) rownum and sorting

 

     The rownum in Oracle is the serial number generated when fetching data. Therefore, if in the sorted data, you need to pay attention when you need to fetch the specified rowmun row data.

 

     Prerequisite: 5 records have been inserted in the loaddata table, the last record id is 200005, then insert into loaddata values('200006','22','AAA');

 

     SQL>select rownum,id,age,name from loaddata;

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         1 200001 22   AAA

         2 200002 22 BBB

         3 200003 22 CCC

         4 200004 22   DDD

         5 200005 22   EEE

         6 200006 22   AAA

 

 

     SQL>select rownum ,id,age,name from loaddata order by name;

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         1 200001 22   AAA

         6 200006 22   AAA

         2 200002 22 BBB

         3 200003 22 CCC

         4 200004 22   DDD

         5 200005 22   EEE

 

     It can be seen that rownum is not a serial number generated according to the name column.

 

     The system assigns the numbers to the records in the order in which they were inserted, and the rowid is also assigned sequentially.

 

     To solve this problem, subqueries must be used

 

     SQL>select rownum ,id,age,name from (select * from loaddata order by name);

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         1 200001 22   AAA

         2 200006 22   AAA

         3 200002 22 BBB

         4 200003 22 CCC

         5 200004 22   DDD

         6 200005 22   EEE

 

 

     This becomes sorted by name, and the correct serial number (from small to large) is marked with rownum.

 

     When there is a large amount of data, it is recommended to add a primary key or index to the field of order by, which will improve the efficiency a lot.

 

     Likewise, to return the intermediate recordset:

 

     SQL>select * from ( select rownum ro,id,age,name from loaddata where rownum < 5 order by name ) where ro > 2; (先选再排序再选)

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         3 200002 22 BBB

         4 200003 22 CCC

 

 

     In general business requirements, it is necessary to sort first, and then return to the intermediate recordset:

 

     SQL>select * from (select t.*,rownum ro from (select id,age,name from loaddata order by name ) t where rownum < 5 ) where ro>=2; (先排序再选再选)

 

     ROWNUM ID     AGE NAME

     ------- ------ --- ------

         3 200002 22 BBB

         4 200003 22 CCC

 

     Note that the SQL statement writing method at this time uses multiple (three-level) nesting. Also note: rownum uses "column aliases".

 

     In fact, this statement is also a classic SQL statement paging algorithm for Oracle data sets: sort first, then select rownum < the maximum value of a certain page, and then select rownum > the minimum value of a certain page.

 

 

 

4. An example:

 

    Requirement: Assuming you don't know the data rules and quantities in the database, print all student data to the terminal.

 

    Solution: rownum is a pseudo column, not in the table, the database first executes from student to traverse the student table.

 

        If there is no where condition filtering, first make a result set, and then look at the conditions behind the select, and pick out the appropriate fields to form the final result set.

 

        If there is a where condition, those that do not meet the condition will be deleted from the first result set, and the following data will continue to be added to judge.

 

        Therefore, if you directly write rownum=2, or rownum>10, the data will not be found.

 

        A subquery can be used to solve this problem: for select rownum, id from book where rownum=2; no data can be found.

 

 

       declare

           v_number binary_integer;

           v_student student%rowtype;

       begin

           select count(*) into v_number from student;

           for i in 1..v_number loop

              select id,name,age into v_student from ( select rownum rn,id,name,age from student ) where rn=i;

              dbms_output.put_line('id: '||v_student.id||' name:'||v_student.name);

          end loop;

       end;

 

      rownum is a pseudo-column added to the result set, that is, a column added after the result set is found first (emphasis: there must be a result set first).

 

      Simply put, rownum is the sequence number of the results that meet the conditions.

 

      It always starts at 1. Therefore, it is impossible for the selected result to not have 1, but to have other values ​​greater than 1.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326352655&siteId=291194637