We had a couple of huge SQL statements (executed within an embedded sqlrpgle program) for which we created separate views - one for each SQL.
The SQL statements were being executed within the programs conditionally. That is, the program had some conditional logic in it (written in RPG) which would determine whether we would execute one query or the other.
Now what we are trying to do is to create a single view which would be an equivalent of the RPG program.
That is somehow include the conditional logic in the view code.
Below is the simplest pseudocode of the view that I could imagine of what I am trying to achieve
if (condition 1 is true)
Select * from table1;
else
Select * from table2;
The if condition logic needs to be part of the view that I am trying to create. Is something like this possible in DB2?
Please note that the condition 1 used above is a very high level representation. The logic is actually comprised of several program calls etc.
Any advise would be appreciated.
If the two parts return the same number of columns, and they are of compatible types, then you could just code the view like this.
CREATE VIEW V AS
WITH C(C) AS ( VALUES (condition) )
SELECT * FROM table1, C WHERE C = 1
UNION ALL
SELECT * FROM table2, C WHERE C = 0
or maybe consider using a table function
Related
I need to datamine all objects and tables from a PL/SQL scripts used to generate reports(which uses multiple tables and objects) which some consists of tens to hundreds/thousands lines of code.I know that things like that can be done automatically in another technologies but im stick to PL/SQL developer.
I wonder if there is any way/tool to do it automatically, rather than just reviewing each script one by one manually and noting everything in excel?
For example test script:
SELECT a,b,c from XYZ1
where d = 'apple'
...
SELECT a,b,g,j FROM XYZ2
WHERE x = '123'
;
and what interests me is result of something for example like:
a,b,c,d used in table XYZ1 and a,b,g,j,x used in table XYZ2
I want to use cursor logic inside the data model's script in order to select some data from tables based on different conditions, but I can't do it from the data model's query script also I can't invoke already stored procedure from db, is there any better option to accomplish this
here are options that I have already tried but got some errors:
I have tried to create procedure and then invoke it from data model as well but it is not possible to call procedure from inside data model's script and i need to reflect procedure's data into data model structure, so i belive this scenario is not good for me.
I have used following solution Anonymous blocks (Procedural Call) data model in Oracle BI Publisher (Oracle Fusion):http://oracleappssolutiions.blogspot.com/2020/12/anonymous-blocks-procedural-call-data.html it is perfect when we need simple 'select' but can't run more complicated logic like this:
DECLARE
type refcursor is REF CURSOR;
xdo_cursor refcursor;
BEGIN
OPEN :xdo_cursor FOR
FOR c IN (select t.* from test t where t.VERSION=2) LOOP
FOR d in (select c.* from record d where CONNECT_BY_ISLEAF = 0 start with d.id. = c.id connect by prior d.id = c.id) loop
select * test
where id=d.id
end loop;
END LOOP;
END;
when i trying to run this i am getting similar errors:
Please share your thoughts/Ideas
Thanks
Try a Pipelined Table Function if you want to use a procedure to generate data.
https://docs.oracle.com/cd/B19306_01/appdev.102/b14289/dcitblfns.htm
If you can get away with just doing select statements with unions and where clause filters, that may be the cleanest way to go.
I'm not sure what the end goal is, but the grouping functionality for templates may help you. There's quite a bit of documentation in the user guides. look for for-each-group in the guide. It's used to take a single flat series of rows/elements, and then create a hierarchy of them, on the fly.
How can I use a plsql code block like this with an Interactive Grid (Using Oracle Apex) :
begin
Query A;
exception when no_data_found then
Query B;
end;
Actually sometimes 'Query A' returns nothing and I want to run 'Query B'. any solution?
An interactive grid has to use a sql-query as source.
a. Write one query and use sql-query as source:
SELECT * FROM A
UNION ALL
SELECT * FROM B WHERE COUNT(SELECT * FROM A) = 0;
b. Write some function which does the work
Read this:
How to return a resultset / cursor from a Oracle PL/SQL anonymous block that executes Dynamic SQL?
But it sounds a little bit strange, that you got one grid for two datasources. This will bring up some problems when manipulating the data.
Open questions
Do you want to modify the data?
Do you want to insert new rows?
Does the user understand what's going on and what he is seeing?
Since there is no apparent way to NOT use an SQL query as the Interactive Grid source, you could maybe (depending on your specific solution) think differently and create an Interactive Grid region for each query. Then you could show one or another when the page loads, using a region server-side condition or even a Dynamic Action.
To expand on other answers with a little specificity, since this is about managing results of 2 different queries, you can put the 2 different queries in 2 different Grid regions. Then on the first region add a Server-side Condition of "Rows returned" and copy the SQL Query into the query input provided. On the 2nd region, you would set "No Rows returned" condition and again copy Query 1 into the SQL input provided.
First off, my background is in SQL Server. Using CTEs (Common Table Expressions) is a breeze and converting it to a stored procedure with variables doesn't require any changes to the structure of the SQL other than replacing entered values with variable names.
In Oracle PL/SQL however, it is a completely different matter. My CTEs work fine as straight SQL, but once I try to wrap them as PL/SQL I run into a host of issues. From my understanding, a SELECT now needs an INTO which will only hold the results of a single record. However, I am wanting the entire recordset of multiple values.
My apologies if I am missing the obvious here. I'm thinking that 99% of my problem is the paradigm shift I need to make.
Given the following example:
NOTE: I am greatly over simplifying the SQL here. I do know the below example can be done in a single SQL statement. The actual SQL is much more complex. It's the fundamentals I am looking for here.
WITH A as (SELECT * FROM EMPLOYEES WHERE DEPARTMENT = 200),
B as (SELECT * FROM A WHERE EMPLOYEE_START_DATE > date '2014-02-01'),
C as (SELECT * FROM B WHERE EMPLOYEE_TYPE = 'SALARY')
SELECT 'COUNTS' as Total,
(SELECT COUNT(*) FROM A) as 'DEPT_TOTAL',
(SELECT COUNT(*) FROM B) as 'NEW_EMPLOYEES',
(SELECT COUNT(*) FROM C) as 'NEW_SALARIED'
FROM A
WHERE rowcount = 1;
Now if I want to make this into PL/SQL with variables that are passed in or predefined at the top, it's not a simple matter of declaring the variables, popping values into them, and changing my hard-coded values into variables and running it. NOTE: I do know that I can simply change the hard-coded values to variables like :Department, :StartDate, and :Type, but again, I am oversimplifying the example.
There are three issues I am facing here that I am trying to wrap my head around:
1) What would be the best way to rewrite this using PL/SQL with declared variables? The CTEs now have to go INTO something. But then I am dealing with one row at a time as opposed to the entire table. So CTE 'A' is a single row at a time, and CTE B will only see the single row as opposed to all of the data results of A, etc. I do know that I will most likely have to use CURSORS to traverse the records, which somehow seems to over complicate this.
2) The output now has to use DBMS_OUTPUT. For multiple records, I will have to use a CURSOR with FETCH (or a FOR...LOOP). Yes?
3) Is there going to a big performance issue with this vs. straight SQL in regards to speed and resources used?
Thanks in advance and again, my apologies if I am missing something really obvious here!
First, this has nothing to do with CTEs. This behavior would be the same with a simple select * from table query. The difference is that with T-SQL, the query goes into an implicit cursor which is returned to the caller. When executing the SP from Management Studio this is convenient. The result set appears in the data window as if we had executed the query directly. But this is actually non-standard behavior. Oracle has the more standard behavior which might be stated as "the result set of any query that isn't directed into a cursor must be directed to variables." When directed into variables, then the query must return only one row.
To duplicate the behavior of T-SQL, you just have to explicitly declare and return the cursor. Then the calling code fetches from the cursor the entire result set but one row at a time. You don't get the convenience of Sql Developer or PL/SQL Developer diverting the result set to the data display window, but you can't have everything.
However, as we don't generally write SPs just to be called from the IDE, it is easier to work with Oracle's explicit cursors than SQL Server's implicit ones. Just google "oracle return ref cursor to caller" to get a whole lot of good material.
Simplest way is to wrap it into an implicit for loop
begin
for i in (select object_id, object_name
from user_objects
where rownum = 1) loop
-- Do something with the resultset
dbms_output.put_line (i.object_id || ' ' || i.object_name);
end loop;
end;
Single row query without the need to predefine the variables.
I have a page that pulls together aggregate data from two different tables. I would like to perform these queries in parallel to reduce the latency without having to introduce a stored procedure that would do both.
For example, I currently have this:
ViewBag.TotalUsers = DB.Users.Count();
ViewBag.TotalPosts = DB.Posts.Count();
// Page displays both values but has two trips to the DB server
I'd like something akin to:
var info = DB.Select(db => new {
TotalUsers = db.Users.Count(),
TotalPosts = db.Posts.Count());
// Page displays both values using one trip to DB server.
that would generate a query like this
SELECT (SELECT COUNT(*) FROM Users) AS TotalUsers,
(SELECT COUNT(*) FROM Posts) AS TotalPosts
Thus, I'm looking for a single query to hit the DB server. I'm not asking how to parallelize two separate queries using Tasks or Threads
Obviously I could create a stored procedure that got back both values in a single trip, but I'd like to avoid that if possible as it's easier to add additional stats purely in code rather than having to keep refreshing the DB import.
Am I missing something? Is there a nice pattern in EF to say that you'd like several disparate values that can all be fetched in parallel?
This will return the counts using a single select statement, but there is an important caveat. You'll notice that the EF-generated sql uses cross joins, so there must be a table (not necessarily one of the ones you are counting), that is guaranteed to have rows in it, otherwise the query will return no results. This isn't an ideal solution, but I don't know that it's possible to generate the sql in your example since it doesn't have a from clause in the outer query.
The following code counts records in the Addresses and People tables in the Adventure Works database, and relies on StateProvinces to have at least 1 record:
var r = from x in StateProvinces.Top("1")
let ac = Addresses.Count()
let pc = People.Count()
select new { AddressCount = ac, PeopleCount = pc };
and this is the SQL that is produced:
SELECT
1 AS [C1],
[GroupBy1].[A1] AS [C2],
[GroupBy2].[A1] AS [C3]
FROM
(
SELECT TOP (1) [c].[StateProvinceID] AS [StateProvinceID]
FROM [Person].[StateProvince] AS [c]
) AS [Limit1]
CROSS JOIN
(
SELECT COUNT(1) AS [A1]
FROM [Person].[Address] AS [Extent2]
) AS [GroupBy1]
CROSS JOIN
(
SELECT COUNT(1) AS [A1]
FROM [Person].[Person] AS [Extent3]
) AS [GroupBy2]
and the results from the query when it's run in SSMS:
C1 C2 C3
----------- ----------- -----------
1 19614 19972
You should be able to accomplish what you want with Parallel LINQ (PLINQ). You can find an introduction here.
It seems like there's no good way to do this (yet) in EF4. You can either:
Use the technique described by adrift which will generate a slightly awkward query.
Use the ExecuteStoreQuery where T is some dummy class that you create with property getters/setters matching the name of the columns from the query. The disadvantage of this approach is that you can't directly use your entity model and have to resort to SQL. In addition, you have to create these dummy entities.
Use the a MultiQuery class that combines several queries into one. This is similar to NHibernate's futures hinted at by StanK in the comments. This is a little hack-ish and it doesn't seem to support scalar valued queries (yet).