Execute stored procedure before select - sql

I am trying to reset my random number seed before executing a SELECT FROM. However, every time I run it, I have to run both statements separately. Ideally, I would like to have the following work:
BEGIN
exec dbms_random.seed(6);
SELECT * FROM myTable
ORDER BY dbms_random.value()
END
I get an error Encountered the symbol DBMS_RANDOM when expecting one of the following :=.(#%; however if I only run exec dbms_random.seed(6); it works.

EXEC[UTE] is a SQLPLUS command, you can not use it into a PLSQL block.
Also, you need an INTO to use a SELECT query within a PLSQL block. If your query can give more than one row, you woud have to use a BULK COLLECT INTO.
Your code could be something like:
DECLARE
something myTable%rowtype;
BEGIN
dbms_random.seed(6);
SELECT *
INTO something
FROM myTable
ORDER BY dbms_random.value();
END;
However, I do not recommend using things like select *; it would be better to explicitly write the columns you need to get.

Also what's the use of an order by in a select into statement which is defined to only return 1 row?
It seems you want to select 1 random row of many which needs a cursor like so:
DECLARE
CURSOR something_cur IS
SELECT *
FROM myTable
ORDER BY dbms_random.value();
something_rec something_cur%ROWTYPE;
BEGIN
dbms_random.seed(6);
OPEN something_cur;
FETCH something_cur INTO something_rec;
CLOSE something_cur;
END;
/

Related

Redshift Cursor

I am trying to get maximum length of each column of a table in Redshift database with this query:
select MAX(LEN(Trim(col1)))mx_len from tbl1;
and insert result into a tmp table like:
tbl1 col1 50
For this, I am trying to write a cursor in redshift to fetch column name one by one and insert data into tmp table. I am getting column names from following query:
select columnname from information_schema.columns where table_name = 'tbl1'
but unable to write a cursor, can anyone help me with this. Thanks in advance.
You haven't describes how you are trying to declare a cursor so it is a little hard to know what the problem is. So I'll describe a generic path to making a cursor and fetching from it.
First a cursor only lives for the duration of the transaction so you must begin and keep open a transaction.
BEGIN;
Next you need to declare the cursor and what data it will contain.
DECLARE <cursor_name> CURSOR FOR SELECT X, Y, Z FROM ...
Then you need to fetch a row from the cursor.
FETCH FORWARD 1 FROM <cursor_name>;
Then get the next row.
FETCH NEXT FROM <cursor_name>;
And on and on. When done close the cursor and end the transaction.
CLOSE <cursor_name>;
END;
Is this what you are doing? Is this not working?

Analyze_Compensation in oracle

Can anyone please tell me for what purpose analyze_compensation is used in oracle?
I got this term in a code in bulk collect. PFB the link:
http://www.oracle.com/partners/campaign/o28plsql-095155.html
Suppose you want to print all the rows and columns of table i.e(Select * from table_name;
) in PL/SQL
THEN in that case :-
dbms_output.put_line() wont be able to print the table data when there is more than one row... Hence we use analyze_compensation() .
It is a procedure , which you need to declare in DECLARE BLOCK of PL/SQL
analyze_compensation is used to print the whole table data i.e Select * from table_name;

"Order by" works in Console but doesn't work in Stored Procedures

I've a problem executing a Stored Procedure in Informix. I'm doing a simple query that it doesn't work. This is the query:
SELECT
first 1 field1,
date1
FROM
historia_t
WHERE
field3 = 1
AND field4 = 1
AND date1 BETWEEN (CURRENT - 1 UNITS YEAR) AND CURRENT
ORDER BY
field1 desc
If I execute the query in DbVisualizer I don't have any problem but if I execute the query in Informix(With stored procedures) I get a sintaxis error in the line with " AND date1 BETWEEN (CURRENT - 1 UNITS YEAR) AND CURRENT " . But the real problem it's in ORDER BY field1 desc;
I don't know why, but sometimes Stored Procedures return errors when you use Order by in them.
Note: Fields are invented because I think they aren't important for the problem.
Thanks in advanced!
When you run a SELECT statement via DB-Access or equivalent, the program takes care of creating a cursor, opening it, fetching the data, closing the cursor, and freeing up the resources used.
Inside a stored procedure, you have to manage this processing. The FOREACH loop does that automatically. If you're using dynamic SQL, there are other statements you can use.
If a SELECT statement may return more than one row, you need the cursor management. If the SELECT statement returns just a single row, you can specify which variable should receive the result. I observe that ORDER BY is immaterial when the SELECT returns a single row — if you have an ORDER BY, there'll be a strong presumption that the query might return more than one row.
For example, this stored procedure works (and returns syssynonyms):
create procedure fk2() returning varchar(128) as tabname;
define t varchar(128);
select tabname into t from informix.systables where tabid = 9;
return t;
end procedure;
But where there's more than one row, you need:
create procedure fk3() returning varchar(128) as tabname;
define t varchar(128);
foreach select tabname into t
from informix.systables
where tabid between 4 and 10
order by tabname # No semicolon permitted (don't ask!)
return t with resume;
end foreach;
end procedure;
This returns:
syscolauth
sysdepend
syssynonyms
syssyntable
systabauth
sysusers
sysviews

EXECUTE IMMEDIATE PL/SQL

Let's say sStorecode is: 00020
The following just executes the select statement to get the accountid at another database STORE in the table STOREINFO, for example connecting to p008081 (where 008 is the substring of the sStorecode and 081 is what I am joining below),
but I am getting errors for some reason (Invalid SQL Statement), can someone help?
EXECUTE IMMEDIATE 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081';
Thanks in advance!
EXECUTE IMMEDIATE is a PL/SQL command. In PL/SQL, the result of a SELECT statement needs to go somewhere. But it your statement, you don't specify where it should go.
So if you expect a single row, you could write:
EXECUTE IMMEDIATE 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081'
INTO l_account_id;
l_account_id is a local PL/SQL variable.
If you expect several row, you could use
EXECUTE IMMEDATE ... BULK COLLECT INTO l_account_tab;
l_account_tab is a PL/SQL collection variable.
Or if you want to work with cursors, you can write:
OPEN account_id_cv FOR 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081';
account_id_cv is a REF CURSOR variable.
Seems like that should be something like this instead:
'select AccountID from STORE.STOREINFO WHERE sStorecode = ''p'||substr(sSTORECODE,3,3)||'081''';

SQL Server 2005: Call a stored procedure from a WHERE clause

I need to make a SELECT with a call of a stored procedure in the WHERE clause.
It should be something like that....
SELECT distinct top 10 i.x, d.droit
FROM v_droit d, v_info i
WHERE d.nomdroit='yy'
AND i.id<>2
AND (select val from (exec up_droits(i.x, d.droit)) <>3
But it does not work...
Any idea?
Don't say to replace the stored procedure with a function because is not possible to use the existing code in a function. So the function is not a valid option. I really need to be able to use a stored procedure
This is achieved by first executing the stored procedure, capturing the output into a #temp table or a #tabel variable, then running your query against the table. Something like this:
declare #droits_table (val ,... );
insert into #droits_table
exec up_droits(param, param);
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id<>2 AND (select val from #droits) <>3
Of course this will not work for you because the up_droits needs the i.x and d.droit parameters from the query. This indicates that your stored procedure should probably be a a view or table valued function.
Sorry but, make it a table valued function rather than stored procedure.
Eg:
Scalar - SELECT id, name FROM test WHERE id < (SELECT dbo.mytestfunction())
Table - SELECT id, name FROM test WHERE id = (SELECT col1 from dbo.mytestfunction())
You can't. The content of the WHERE clause must be a search expression.
Is the reason that the code doesn't work as a function because it modifies some data? If so, then you're out of luck, functions used in where clauses must be immutable.
If the stored procedure doesn't modify any data, you may be able to wrap it inside of a function.
If you are on SQL Server I don't think you can do what you propose.
But one thing you can do is build dynamic queries, but be careful doing it because they open up many interesting problemareas.
The syntax is :
EXEC #<query>
But anotherthing you can do, which is probably much better for you, is to make the up_droits function deliver it's results in a temp table, if you select into a #table it is temporary for the duration of your function/procedure scope
declare procedure up_droits() as
select val .. into #temp
So what you do is create a procedure
create procedure Top10FromDroit
begin
exec up_droits
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id2 AND (select val from (#temp) 3
Hopefully that will give you the results you want to achieve.
If at first you don't succeed, code around it^^
Could anyone of you explain reasons for executing dynamic SQl inside stored procedure. I know very few situations when you need them - but really very few. 99.9% (or 999 of a 1000) of execute strings could be rewritten as normal sql statements with parameters.
The very same is with Selects that have functions inside select or where clauses.
Try to think about your sets of data, not about procedural ways how to solve it.