简体   繁体   中英

Oracle SQL Rownum syntax issue

I am trying to write a query with the following capability:

1) Selects everything from table called EMPLOYEE that match the $city variable to the table column CITY as well as the variable $search with the column NAME inside my EMPLOYEE table without having to be concerned about the case sensitivity.

2) I want to limit my results to displaying rows 11-20

I started with the following:

select * from (select rownum rn, NAME, ADDRESS, POSTAL, PHONE, MAP from EMPLOYEE) where rn >= 11 and rn <= 20;

This allows me to see rows 11-20 without narrowing the results to a specific city and search word which was a start.

I tried to modify the above statement to reach my goal with the following:

select * from (select rownum rn, NAME, ADDRESS, POSTAL, PHONE, MAP from EMPLOYEE) where rn >= 11 and rn <= 20 and CITY= $city and LOWER(NAME) like LOWER('%$search%');

I also tried changing the order of the statement to:

select * from (select rownum rn, NAME, ADDRESS, POSTAL, PHONE, MAP from EMPLOYEE) where CITY= $city and LOWER(NAME) like LOWER('%$search%') and rn >= 11 and rn <= 20;

I am fairly new to Oracle...

If someone could provide an explanation as to why my thought process does not work that would also be appreciated.

I have a visceral reaction to rownum because it is a strange beast. It is incremented when data is output -- the very last step of the query. The irony is, if no data is returned by the query then rownum is never incremented. This has the effect that rownum > 1 will never return results, because the first row is never returned in the result set.

I would recommend that you use row_number() instead. This is slightly more expensive performance wise, but it will do the right thing. Here is an example:

select e.* 
rom (select row_number() over (order by name) as rn, NAME, ADDRESS, POSTAL, PHONE, MAP
     from EMPLOYEE
    ) e 
where rn >= 11 and rn <= 20;

The behavior for rownum is actually documented pretty well in the Oracle documentation .

EDIT:

Of course, rownum does work in the subquery as you are using it. You just need to move your where conditions into the subquery:

select e.*
from (select rownum rn, NAME, ADDRESS, POSTAL, PHONE, MAP
      from EMPLOYEE e
      where CITY = $city and LOWER(NAME) like LOWER('%$search%')
     ) e
where rn >= 11 and rn <= 20;

Concerning part 2 of your question: "I want to limit my results to displaying rows 11-20". Strictly speaking, this requirement does not have much sense. Oracle interprets table's data as a heap, that does not have any sequence, and Oracle does not guarantee an order of fetched data as long as you don't specify an "order by" clause in your query. Because you have not mentioned a sorting of your query output, the "order by" clause is not required for you. As a result your Oracle query will provide a hazard sequence of data.

Because you want to restrict an amount of output lines to 10, your query (without substitution) might be written as follows:

 select NAME, ADDRESS, POSTAL, PHONE, MAP from EMPLOYEE where rownum < 11;

Concerning a variable substitution, it depends on kind of query execution. Eg interactively from SQL*Plus, from a *.sql script, from a call of sql script from shell script on UNIX or another OS, from HERE-document, embedded in a shell script, from PL/SQL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM