JPA dynamic order by clause

I need to dynamically build the order by clause of my query.
I tried this:
<named-query name="list">
  <query>
    <![CDATA[
      SELECT p FROM Person p
      ORDER BY :orderby
    ]]>
  </query>
</named-query>
@SuppressWarnings("unchecked")
public List<Person> list(String sort) {
  Query query = getEntityManager().createNamedQuery("list");
  query.setParameter("orderby", sort);
  return query.getResultList();
}But at runtime it throws an exception:
com.microsoft.sqlserver.jdbc.SQLServerException:
L'elemento SELECT identificato da ORDER BY 1 include una variabile nell'espressione che identifica la posizione di una colonna.
Le variabili sono consentite solo nell'ordinamento in base a un'espressione che fa riferimento a un nome di colonna.The translation of the italian message is something like:
The SELECT element identified by ORDER BY 1 includes a variable that identifies the position of a column.
The valid variables in the order by clause must refer to the name of a columnThe value of the parameter sort is_ the name of a column!
Any hint?

My solution was to append the order clause to an "namedQuery" like this:
- declare the named query as usual, with annotation
- create a simple helper function like findNamedQuery to find the query string for a given class and queryName (using reflection)
- if you need to execute the query without sort order - use EntityManager.createNamedQuery (as usual)
- BUT: if you want to sort data: use EntityManager.createQuery with the string obtained from findNamedQuery and the sort clause
I guess the is a performance penalty, but.. .it works.

Similar Messages

  • Dynamic ORDER BY clause

    Hi all,
    I'm creating a webpage using jsp thats accessing a mysql database. When I get a ResultSet from a query, I was wondering if anyone could give me some pointers on how I could sort the results based on a field name that someone clicks on. For example:
    Column1   Column2
    5         2
    8         1
    3         6I'd like to create hyperlinks on the field names so when a user clicks on it, it will sort the data in according to that field. Here is my code that I am trying to modify:
    public String displayResultSet(ResultSet rs)
    {// return a result set as an html table
         String htmlTable = "";
         try {
              // get the number of columns
              ResultSetMetaData rsmd = rs.getMetaData();
              int numColumns = rsmd.getColumnCount();
              // create a table and display the mysql field names as table headers
              htmlTable += "<TABLE>\n<TR>\n";
              for(int i=1; i<=numColumns; i++)
                   htmlTable += "<TH>" + rsmd.getColumnName(i) + "</TH>\n";
              htmlTable += "</TR>\n\n";
              // create an object to temporarily hold a piece of ResultSet data
              Object cellData = null;
              // display the data in the ResultSet in rows of an html table
              while(rs.next())
              {// while the ResultSet has more rows, convert them to html
                   htmlTable += "<TR>";
                   for(int j=1; j<=numColumns; j++)
                   {// if the data is not null, display it, otherwise display a blank space
                        cellData = rs.getObject(j);
                        if(cellData != null)
                             htmlTable += "<TD>" + rs.getObject(j) + "</TD>\n";
                        else
                             htmlTable += "<TD> </TD>\n";
                   htmlTable += "</TR>\n\n";
              htmlTable += "</TABLE>\n\n";
         catch (Exception e)
              { return("Error accessing database: " + e); }
         return htmlTable;
    }Any help or references to where I can read up on it would be appreciated. Thanks
    Leon

    Your display code should not be mixed in with your database code. That functionality should be seperated classes.
    Generally GUIs do the ordering themselves. They do not repeatedly call the database.
    But if you want you pass in a descriptor that defines the fields that will be ordered on. You optionally map that to the exact database field names. You then use StringBuilder to construct the entire SQL string and add the order by clause dynamically at the end. Then you execute it.

  • Dynamic ORDER BY clause - Possible different data types...

    I have a lexical parameter in my ORDER BY clause:
    ORDER BY &P_ORDER_BY
    My problem is that I have to designate this parameter as either a date, character or number, but the user defined column being ordered by could be any one of these. When I designate the parameter as a character type, and a number data type column is chosen, it orders by that value, but it orders it as though it were a character field, referencing the initial digit and not the overall numeric value. If I choose a number parameter type, and a character value is chosen, I get an invalid number error, and so on.
    Anyone have any ideas how I can do this?

    Okay, now we're on the right track. The lexical parameter I'm using allows the user to choose from a list of the columns being retrieved in the SELECT statement, so it will always be one that's in there, as you said. Now, since I don't know which one it's going to be, I can't just make all but one of them 'None' for the break order, BUT, what I intended to do was to add a column to the SELECT statement that would always return the column they chose, and I could put the break order on that column, leaving all the rest 'None'. However, in the past, this has created 2 problems for me.
    1.) As I mentioned in the first post, the column being returned could have a data type of character, number or date, but the parameter must be designated as only one of these. So, if the user chooses to order by a column having a value with a data type other than what the parameter is designated to be, then I get errors, it doesn't order correctly, etc...
    2.) This is the strange, but anytime I've marked all but one column as 'None' for the Break Order, my child data doesn't always stay with the parent. For example, the report is on an IT request database. The 'group fields' consist of data elements that are demographic info.of a request (requester, date requested, description, etc...), and the details for each request list out the comments that have been made in the system for that request. The problem I'm seeing when I set the break orders this way is that each request displays not only its own comments, but it lists out comments for other requests as well, and there doesn't seem to be any logic to which request's comments it lists in addition to its own, it just lists as many as will fit on the page...I don't know if I explained that very well, but that's what's happening.
    Does any of that make sense? Any ideas?

  • How to make an ORDER BY clause dynamic

    is there anyway to make the ORDER BY clause in an SQL query within a DB control
    dynamic? I have tried to pass a String of the column name and place it in the
    statement within {}, but it doesn't work

    "Mark" <[email protected]> wrote:
    >
    is there anyway to make the ORDER BY clause in an SQL query within a
    DB control
    dynamic? I have tried to pass a String of the column name and place
    it in the
    statement within {}, but it doesn't workDid you find how ? please let me know, I also need to have a dynamic order by
    clause.

  • Dynamic Order By on Report Builder 10g

    Hi,
    How can I do a dynamic order by clause using user parameters on Report Builder 10g? I need to set dynamically the column and the direction on the clause.
    Thanks.
    Bruno Galletti
    Brazil.

    Hi Bruno / Rainer,
    I am implementing the same solution, and after adding the lexical parameter reference in the SQL statement and calling the report from Oracle Forms the report failed with the following error on the report server:
    Terminated with error: <br>REP-300: missing expression select wcsr_no , wcsr_date , wcsr_rec_week_zone , wcsr_loc_house_num || ' ' || wcsr_loc_pre_dir || ' ' || wcsr_loc_street_name || ' ' || wcsr_loc_street_type || ' ' || wcsr_loc_post_dir || ' ' || wcsr_loc_unit || ' ' || wcsr_loc_city || ' ' || wcsr ==>
    No change has been done to the SQL statement except adding the &p_orderby parameter at the end of the query.
    Any suggestions? Are all parameters defined as "bind" parameters on the Repotr Object Navigator.?
    Thanks
    Gabriel Aguirre
    [email protected]

  • Dynamic order by with updateable report

    I have a region of type sql query (updateable report)
    I want to add a dynamic order by clause based on the value of a page item
    ie order by nvl(:PX_ORDER, 1)
    I can get the dynamic ordering to work using the 'function returning sql query' reqion type but having a little problem with the sql query type above.
    nb. Have also tried ORDER BY decode(:PX_ORDER, 2, 2, 1) but no luck.

    Thanks Vikas,
    I was using column numbers in the decode. Needed to specify the actual column_name including any "" surrounding it.
    decode(:PX_ORDER, 2, "COL2_NAME", "COL1_NAME")
    works
    any ideas on how to dynamically flip the ASC, DESC ordering in a SQL statement?? The 'ASK TOM' note you mentioned above states you should use dynamic query strings if this functionality is required.
    Unfortunately updateable report regions can't be created using dynamic query strings.

  • Order by clause  Dynamic in Oracle function

    How can i get order by Clause Dynamic in Oracle function
    My function Returns sql query with SYS_REFCURSOR . and i will pass the order by column as input parameter
      create or replace
    FUNCTION TEST_SSK
            p_srot  number
    RETURN SYS_REFCURSOR
    AS
    C_testssk SYS_REFCURSOR;
    BEGIN
    OPEN C_TESTSSK FOR
    SELECT LOAN_CODE,LOAN_DATE,DUE_DATE,LOAN_AMT FROM LOAN_MASTER
    order by P_SROT;
    return C_testssk;
    end;Edited by: user10736825 on Dec 22, 2010 11:34 AM

    you can go for a dynamic query ;)
    create or replace
    FUNCTION TEST_SSK
            p_srot  number
    RETURN SYS_REFCURSOR
    AS
    C_testssk SYS_REFCURSOR;
    l_str VARCHAR2(4000);
    l_order VARCHAR2(100);
    BEGIN
    l_str := 'SELECT LOAN_CODE,LOAN_DATE,DUE_DATE,LOAN_AMT FROM LOAN_MASTER ';
    IF p_sort = 'LC'
    THEN
      l_order := ' ORDER BY LOAN_CODE ';
    ELSIF p_sort = 'LD'
    THEN
      l_order := ' ORDER BY LOAN_DATE ';
    END IF;
      l_str := l_str || l_order ;
    OPEN C_TESTSSK FOR l_str;
    return C_testssk;
    end;

  • Sorting character column ( used in order by clause dynamically)

    Hi,
    I need help on sorting character-based numbers. Like say, I want to sort customers based on street numbers(which is a character string being used in the
    order by clause) they live in.
    The criteria are :
    i. Numbers must take precedence.
    This being a character string, 1000001 comes before 2. This shouldn't happen. And you cannot use to_number
    since using it with a string having characters in it would raise an error.
    ii. If only a single alphabet occurs as the last character, then treat the whole string as a number except the last character and then sort it
    as if sorting a number. Something like : if you have 1000A, 200D, 200B, 1000X, the result would be 200B,200D,1000A,1000X.
    iii. if a character occurs elsewhere in the string, then perform the search normally as if performing a character search.
    The output of the following data :
    100
    A101
    B100A
    110C
    C120B
    120
    100020
    120C
    C1100
    100D
    would be like :
    100
    100D
    110C
    120
    120C
    100020
    A101
    B100A
    C120B
    C1100
    Please note that the sort is being done dynamically, so I could have access to the values of the street numbers only during run time.
    Any help is really appreciated.
    Thanks in advance.
    Regards,
    Anil.

    Create a function to test whether the column is numeric :
    create FUNCTION is_numeric(v_number VARCHAR2)
    RETURN INTEGER
    IS
    l_number NUMBER;
    BEGIN
    IF INSTR(UPPER(v_number),'E') > 0 THEN
    RETURN 0;
    END IF;
    l_number := TO_NUMBER(v_number);
    RETURN 1;
    EXCEPTION
    WHEN OTHERS THEN
    RETURN 0;
    END;
    And try this query
    Assume the table name is TEST with column STREET
    select * from TEST
    order by case is_numeric(STREET) when 1 then LPAD(STREET,20, ' ') else STREET end
    Please make sure that 20 mentioned above is the column size for STREET.
    Hope this helps.
    -Nags

  • [JPA/TOPLINK] is the function "lower" supported in "order by" clause?

    In EJB-QL
    I can use lower() or upper() in where clause.
    But there is always a parse exception thrown when i tried to use it in main clause or order by clause.
    works:
    select s from Student s where lower(s.name) like 'm%'
    exception thrown:
    select s from Student s where s.name like 'm%' order by lower(s.name)
    OR --------------
    Why i am asking this is that the resultset returned from database is not alphabetical sorted but ascii sorted, which means any characters with upper case is always prior to the ones with lower case.
    If EJB-QL doesn't support using lower() in order by clause, do I have any other options to avoid this problem?
    BTW, it is the Oracle 10g we are using as DB
    many thanks,
    Xuphey
    Edited by: Xuphey on Nov 29, 2007 1:33 AM

    If you want to do this, you'd have to use dynamic SQL (execute immediate or DBMS_SQL). For the easier 'execute immediate' approach, you'd do something like
    create or replace someProc( someArg varchar2 )
    as
      strSQL varchar2(4000)
    begin
      strSQL := <<string containing your SQL statement up to the order by clause>>
      strSQL := strSQL || 'ORDER BY ' || someArg
      execute immediate strSQL;
    endJustin

  • Order by clause require dynamic value

    Hi
    I want to bind parameters to orderby clause. In where clause with bind parameter works fine. But in orderby clause ive done similar steps to have a dynamic sort which will be passed from the previous page in a session variable. Although it didnt show any error at the backend where i can see data getting binded, but no sorting is taking place.
    Can u help me to solve this.
    regards
    Jayashri

    Jayashri,
    I have tested this and you are right. And there does occur an error at the backend, only you wont see it unless you run with BC4J debug mode turned on. You can do this by providing -Djbo.debugoutput=console to the JVM. When running inside JDeveloper, you can accomplish this by going to Project Properties => PRofiles => Development => "Runner", and fill this in at the "Java Options" field.
    Doing that will show the reason of the problem. When a view object is queried, BC4J actually performs 2 queries. One to obtain the 'estimated row count', and then one to obtain the action rows.
    Now suppose your query looks like this:
    SELECT <somefields> FROM <table>
    WHERE <field> = :1 ORDER BY :2
    Bc4j will construct the following query to obtain the estimated rowcount:
    SELECT count(1) FROM (SELECT <somefields> FROM <table> WHERE <field> = :1)
    As you can see, it does NOT include the ORDER BY of the original query in this statement, probably for performance reasons (why order the set if you are only interested in the count). Unfortunately, it WILL try to bind both :1 AND :2 to this query, but because there is only one bind variable in this query, this throws an java.sql.SQLException which is unfortunately trapped somewhere in BC4J code, and not shown in the regular log file.
    I am pretty confident that this is actually a BC4J bug (or known restriction). You could post this problem at the JDeveloper Forum to determine this (without mentioning JHeadstart, because this would also happen if you wrote your own code for binding these parameters).
    As for a workaround, you could try the following:
    1.) Remove the (bind parameter from) the order by clause on the ViewObject
    2.) Remove that same bind parameter from the "Query Bind Parameters" property.
    You should now have gone back to a scenario where there are only bind parameters on the where clause. You would need to set the OrderBy clause programatically now. To do this, extend the JhsDataAction for this page, and override the method 'applyIterBindParams()'. Before calling super, try something like:
    ViewObject vo = ib.getRowSetIterator().getRowSet().getViewObject();
    vo.setOrderByClause(<your dynamic orderby>);
    Kind regards,
    Peter Ebell
    JHeadstart Team

  • Can i assign an 'order by' clause dynamically in forms ??

    I know it's possible to assign an 'order by' clause in reports with lexical parameter.
    for example..
    select A
    from TABLE
    where A is not null
    &V_ORDERBY
    In this, v_orderby might be 'order by name' like that,,,
    can i assign an 'order by' clause dynamically IN FORMS ??
    If you understan my question, please answer to me,,,ㅜㅜ

    Have you tried this build-in function?
    SET_BLOCK_PROPERTY('[BLOCK_NAME]', ORDER_BY, 'SORTCOL1, SORTCOL2...');
    Where 'SORTCOL1, SORTCOL2...' are the table columns name.

  • Dynamically change the value in order by clause (urgent)

    Could any one help atall with this.
    I have a cursor within a procedure and i want to be able to pass parameter into the procedure so that the record fetched by the cursor can be ordered by the parameter passed in.
    For instance
    create or replace procedure select_all(p_order_by in varchar2) is
    cursor r_cur (c_order_by in varchar2) is
    select empno,empname,job,manager,salary
    from emp
    ordry by c_order_by;
    r_rec r_cur%rowtype;
    lv_order_by varchar2(30);
    begin
    lv_order_by := p_order_by;
    for r_rec in r_cur(lv_order_by) loop
    dbms_output.put_line(empno||empname||job||manager||salary);
    end loop;
    end;
    I have obviously done it as written above but the output is not ordered by the value i passed into the procedure when ran. Is the a better way to achieve the desired result?

    I handle dynamic order by using dynamic sql
    create or replace procedure select_all
                   (p_order_by  in varchar2) is
    TYPE               RefCurTyp is REF CURSOR;
    CV                    REFCURTYP;
    v_sql_stmt  VARCHAR2(4000) ;
    r_rec r_cur%rowtype;
    BEGIN
      v_sql_stmt := 'select empno,empname,job,manager,salary '||
                                ' from emp ' ||
                                ' ORDER BY '||p_order_by ;
      open CV for v_sql_stmt;
      loop
            fetch CV into r_rec ;
                    exit when CV%NotFound;
            dbms_output.put_line(r_rec.empno||' '||r_rec.empname||' '||r_rec.job||' '||r_rec.manager||' '||r_rec.salary);
      end loop;
    close CV;
    end;

  • Dynamic values in order by clause

    hi,
    i want to sort data dynamically by giving any column name
    example
    select * from emp
    order by :isortcolname :isortorder
    isortcolname is any thing like eno, ename, sal, deptno
    isortsrder is like asc, desc
    thanks

    You could do something like this...
    SQL> ed
    Wrote file afiedt.buf
      1  with t as (select '&sortord' as sortord, '&sortcol' as sortcol from dual)
      2  select emp.*
      3  from emp, t
      4  order by decode(sortord,'ASC',decode(sortcol,'EMPNO',empno,'SAL',sal,'DEPTNO',deptno,1),1),
      5*          decode(sortord,'DESC',decode(sortcol,'EMPNO',empno,'SAL',sal,'DEPTNO',deptno,1),1) desc
    SQL> /
    Enter value for sortord: ASC
    Enter value for sortcol: SAL
    old   1: with t as (select '&sortord' as sortord, '&sortcol' as sortcol from dual)
    new   1: with t as (select 'ASC' as sortord, 'SAL' as sortcol from dual)
         EMPNO ENAME      JOB              MGR HIREDATE                    SAL       COMM     DEPTNO
          7369 SMITH      CLERK           7902 17-DEC-1980 00:00:00        800                    20
          7900 JAMES      CLERK           7698 03-DEC-1981 00:00:00        950                    30
          7876 ADAMS      CLERK           7788 23-MAY-1987 00:00:00       1100                    20
          7521 WARD       SALESMAN        7698 22-FEB-1981 00:00:00       1250        500         30
          7654 MARTIN     SALESMAN        7698 28-SEP-1981 00:00:00       1250       1400         30
          7934 MILLER     CLERK           7782 23-JAN-1982 00:00:00       1300                    10
          7844 TURNER     SALESMAN        7698 08-SEP-1981 00:00:00       1500          0         30
          7499 ALLEN      SALESMAN        7698 20-FEB-1981 00:00:00       1600        300         30
          7782 CLARK      MANAGER         7839 09-JUN-1981 00:00:00       2450                    10
          7698 BLAKE      MANAGER         7839 01-MAY-1981 00:00:00       2850                    30
          7566 JONES      MANAGER         7839 02-APR-1981 00:00:00       2975                    20
          7788 SCOTT      ANALYST         7566 19-APR-1987 00:00:00       3000                    20
          7902 FORD       ANALYST         7566 03-DEC-1981 00:00:00       3000                    20
          7839 KING       PRESIDENT            17-NOV-1981 00:00:00       5000                    10
    14 rows selected.
    SQL> /
    Enter value for sortord: DESC
    Enter value for sortcol: EMPNO
    old   1: with t as (select '&sortord' as sortord, '&sortcol' as sortcol from dual)
    new   1: with t as (select 'DESC' as sortord, 'EMPNO' as sortcol from dual)
         EMPNO ENAME      JOB              MGR HIREDATE                    SAL       COMM     DEPTNO
          7934 MILLER     CLERK           7782 23-JAN-1982 00:00:00       1300                    10
          7902 FORD       ANALYST         7566 03-DEC-1981 00:00:00       3000                    20
          7900 JAMES      CLERK           7698 03-DEC-1981 00:00:00        950                    30
          7876 ADAMS      CLERK           7788 23-MAY-1987 00:00:00       1100                    20
          7844 TURNER     SALESMAN        7698 08-SEP-1981 00:00:00       1500          0         30
          7839 KING       PRESIDENT            17-NOV-1981 00:00:00       5000                    10
          7788 SCOTT      ANALYST         7566 19-APR-1987 00:00:00       3000                    20
          7782 CLARK      MANAGER         7839 09-JUN-1981 00:00:00       2450                    10
          7698 BLAKE      MANAGER         7839 01-MAY-1981 00:00:00       2850                    30
          7654 MARTIN     SALESMAN        7698 28-SEP-1981 00:00:00       1250       1400         30
          7566 JONES      MANAGER         7839 02-APR-1981 00:00:00       2975                    20
          7521 WARD       SALESMAN        7698 22-FEB-1981 00:00:00       1250        500         30
          7499 ALLEN      SALESMAN        7698 20-FEB-1981 00:00:00       1600        300         30
          7369 SMITH      CLERK           7902 17-DEC-1980 00:00:00        800                    20
    14 rows selected.but I would really question why there is a need for dynamically ordering data using SQL. That's the sort of thing that reporting tools allow once they've retrieved the data, and that's usually the best place for it.

  • How to use "Order by" clause dynamically on LOV values in 10g r2 forms

    Hi ,
    I have following requirement,please guide me.
    1 Create a List Of Values with 2 fields, Code and Description
    2. Do not use order by clause in record Group Query
    3. Attach this LOV to a field in Form
    4. When user invokes the LOV user will see two fields in LOV with header as Code and Description
    5. Now when user clicks on Column Header “Code” then LOV should be sorted on Code
    6. And if User clicks on Column Header “Description” then LOV should be sorted on Description
    Thanks in Advance.

    Kindly post this problem in this forum ->
    [Forms Forum|http://forums.oracle.com/forums/forum.jspa?forumID=82]
    And, close this thread by marked it as answered. ;)
    Regards.
    Satyaki De.

  • Order by clause in PL/SQL cursors

    I am trying to execute a procedure with some input parameters. I open a cursor
    with a select statement. However, the order by clause in the query does not
    recognize parameter sent through the procedure input parameters.
    For example:
    open <<cursor name>> for
    select id from member order by <<dynamic parameter>>" does not work (Compiles fine but does not return the right result).
    But if I try and give a static order by <<column name>> it works. Is the
    order by clause in the PL/SQL a compile time phenomenon?
    I have also tried it through dynamic sql. All the other parameters work except the order by <<parameter>> asc|desc
    Also "asc" and "desc" does not work if given dynamically.
    What alternatives do I have?
    null

    I don't think order by can be dynamic in a cursor, but it sure can be using dynamic sql. The only issue is that you must do a replace in the sql string with the dynamic variable. For example:
    create or replace procedure test_dyn(p_col in varchar2, p_order in varchar2) as
    q varchar2(500);
    u_exec_cur number;
    u_columnnumber NUMBER;
    u_columndate DATE;
    u_columnvarchar varchar2(50);
    u_cur_count number;
    u_ename varchar2(20);
    u_sal number;
    begin
    q := 'select ename, sal from scott.emp order by p_col p_order';
    -- got to do these two replaces
    q:= replace(q,'p_col',p_col);
    q:= replace(q,'p_order',p_order);
    u_exec_cur := dbms_sql.open_cursor;
    dbms_sql.parse(u_exec_cur,q,dbms_sql.v7);
    dbms_sql.define_column(u_exec_cur, 1, u_columnvarchar, 20);
    dbms_sql.define_column(u_exec_cur, 2, u_columnnumber);
    u_cur_count := dbms_sql.execute(u_exec_cur);
    loop
    exit when (dbms_sql.fetch_rows(u_exec_cur) <= 0);
    dbms_sql.column_value(u_exec_cur, 1, u_ename);
    dbms_sql.column_value(u_exec_cur, 2, u_sal);
    dbms_output.put_line(u_ename);
    dbms_output.put_line(u_sail);
    --htp.p(u_ename);
    --htp.p(u_sal);
    end loop;
    end;
    show errors;
    Now when when I execute my procedure I can change the order by clause all I want, for example:
    SQL> set serveroutput on;
    SQL> exec gmika.test_dyn('sal','asc');
    SMITH
    800
    ADAMS
    1100
    WARD
    1250
    MARTIN
    1250
    MILLER
    1300
    TURNER
    1500
    ALLEN
    1600
    JLO
    2222
    BLAKE
    2850
    JONES
    2975
    SCOTT
    3000
    FORD
    3000
    LOKITZ
    4500
    KING
    5000
    JAMES
    5151
    JAMES
    5555
    PL/SQL procedure successfully completed.
    SQL>
    null

Maybe you are looking for