2

In Oracle's SQL Developer, I can execute a "dynamic" SQL select statement in the Script Output pane with something like:

script
  var tabName = 'all_users';
  sqlcl.setStmt('select * from ' + tabName);
  sqlcl.run();
/

Now, I am wondering if it is possible to execute a dynamic select statement such that its result is displayed in the result grid.

René Nyffenegger
  • 39,402
  • 33
  • 158
  • 293
  • i think you can wrap your dynamic sql in a pipelined table function and create a view around it using the table operator – MarEll Dec 11 '20 at 07:36
  • This assumes that the dynamic sql statement always returns the same number, names and data types of the columns. – René Nyffenegger Dec 11 '20 at 13:39

2 Answers2

1

SqlDev is implemented in Java which includes Nashorn scripting engine. Therefore, you can basically execute JDBC in your Nashorn script. Here is one way to do it.

Paste

select REGIONS,
COUNTRIES,
LOCATIONS,
DEPARTMENTS,
JOBS,
EMPLOYEES,
JOB_HISTORY,
TM_USER_INFO,
USER_ROLES,
PAYMENT_PRICE_SHOP,
SHOP_USER from dual

into your worksheet.

Open "Code Outline" panel. Type "arbori", or open the following "querySQL.arbori" file:

include "std.arbori"

prelude: runOnce -> {
    var ConnectionResolver = Java.type('oracle.dbtools.db.ConnectionResolver');  
    var connectionList = ConnectionResolver.getConnectionNames();
    var conn = ConnectionResolver.getConnection('IdeConnections%23local_hr');
}

queries: [node) column -> {
    var node = tuple.get('node');
    var table = target.input.substring(
            target.src[node.from].begin,
            target.src[node.to-1].end
        );    
    var query = 'select * from ' + table;
    var ps = conn.createStatement();
    var rs = ps.executeQuery(query);
    while( rs.next() )
        print(rs.getString(1));

}

It outputs the first column of each table to the standard java output

enter image description here , so it would require some reverse engineering to get a handle to the SqlDev script output panel and channel the result there.

Tegiri Nenashi
  • 3,066
  • 2
  • 19
  • 20
1

Dynamic SQL can be displayed in an Oracle SQL Developer grid using a function returning a ref cursor (sort of), a polymorphic table function (18c+), or Oracle Data Cartridge (requires custom PL/SQL packages and types).

Function Returning Ref Cursor

As explained in this answer, the output from a function returning a ref cursor can be displayed in the "Output Variables" window. The example from the answer used static SQL, but it's pretty easy to make it dynamic:

create or replace function refcursor_function return sys_refcursor as
  c sys_refcursor;
begin
  open c for 'select * from all_objects';
  return c;
end;
/

The downside is that getting the results takes a few more clicks than a normal query, and the Output Variables grid is not nearly as powerful as the regular results grid. If you just need a window for viewing and copying and pasting, Output Variables is good enough. But it doesn't allow any advanced GUI features.

Polymorphic Table Function

Since Oracle 18c, you can create a polymorphic table function that accepts input and has variable output. You have to program how to handle the tables and columns, but if you just need simple pass-through logic it's not that difficult. See my answer here for an example of a query that returns every column from a table excluding specific columns. The results are "regular" SQL as far as any program knows, and will work in any grid GUI.

Oracle Data Cartridge

My open source program Method4 can run dynamic SQL in SQL. After you download and install the packages and types, you can write a SQL statement that generates another SQL statement. If you need to use PL/SQL to generate the query, you may need to use a PL/SQL WITH function. Like the polymorphic table function, the results look like normal SQL and will work in any grid.

select * from table(method4.dynamic_query(
    q'[
        --Query that builds another query.
        select replace(
            q'!
                select * from #TABLE_NAME#
            !', '#TABLE_NAME#', table_name) sql_statement
        from
        (
            --Enter your script here that returns a table name to select from.
            select 'ALL_USERS' table_name
            from dual
        )
    ]'
));

You may want to add some details about what exactly you're trying to do and why; that might help narrow down the possible solutions.

Jon Heller
  • 34,999
  • 6
  • 74
  • 132
  • The few more mouse clicks required by the function that returns a ref cursor is what caused me to ask this question. I am already able to print the dynamic SQL text somewhere (shell, dbms_output, even Excel etc) and then copy/paste it to the SQL editor. So no real benefit here. The other approaches look great at first sight, but Oracle parses the dynamic SQL text *once* at the function's first invocation and then does not recognize if the SQL text has changed on subsequence invocations. So, these are not really suitable for my purposes as well. – René Nyffenegger Dec 12 '20 at 07:52
  • Don't get me wrong, I do appreciate the time you took to answer my question. – René Nyffenegger Dec 12 '20 at 07:52
  • @RenéNyffenegger I'm not sure about the PTF solution, but I just modified Method4 to force a hard-parse on every execution. (The program had that functionality before but was not consistently using it among all four functions.) – Jon Heller Dec 13 '20 at 06:54
  • I just skimmed over your github repository. The purge of the SQL statement does indeed look promising. But give me some time to evaluate it, I won't probably come around it during the next week. – René Nyffenegger Dec 13 '20 at 18:50
  • I am impressed by your work and so far this seems to be the only way to display a dynamic sql statement's result in SQL developer. Unfortunately, the execution of `dbms_shared_pool.purge` (which is central to your solution) requires non standard privileges that are not granted in all environments I am working in. As much as I like your solution, I think it's a workaround for a functionality that SQL developer almost provides and could provide. In summary, I wait for a "real" SQL developer solution so that I don't yet accept your valuable contribution as answer to my question. – René Nyffenegger Dec 21 '20 at 08:49
  • @RenéNyffenegger Thanks. I understand your concern about `dbms_shared_pool` - I'm trying to find ways to simplify or reduce the permissions but have been unsuccessful so far. – Jon Heller Dec 22 '20 at 00:55