Trying to store a procedure in Oracle 11g to monitor tablespace storage - sql

I'm trying to store this code in Oracle and everytime I get an error of compilation. I search about storing procedures without parameters and I didn't find a solution to fix this.
Here is the procedure that I'm trying to store:
CREATE OR REPLACE PROCEDURE Espacio_libre
BEGIN
select df.tablespace_name "Tablespace",
totalusedspace "MB Usados",
(df.totalspace - tu.totalusedspace) "MB Libres",
df.totalspace "MB Totales",
round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace))
"Pct Libre"
from
(select tablespace_name,
round(sum(bytes) / 1048576) TotalSpace
from dba_data_files
group by tablespace_name) df,
(select round(sum(bytes)/(1024*1024)) totalusedspace, tablespace_name
from dba_segments
group by tablespace_name) tu
where df.tablespace_name = tu.tablespace_name;
END Espacio_libre;
/
Thanks guys.

when you create a stored procedure in oracle, you are using PL/SQL code instead of SQL.
There is no select column,[column] from table in pl/SQL
You have to do 'Select column into variable from table'.
Please see the documentation below to learn elementary of PL/SQL programming.
[https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/selectinto_statement.htm][1]

create GLOBAL TEMPORARY table test22jan16 (tablespace_name varchar2(100),MB_Libres varchar2(100),MB_Totales varchar2(100),Pct_Libre varchar2(100))
ON COMMIT DELETE ROWS;
insert into test22jan16
select df.tablespace_name ,
(df.totalspace - tu.totalusedspace),
df.totalspace,
round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace))
from
(select tablespace_name,
round(sum(bytes) / 1048576) TotalSpace
from dba_data_files
group by tablespace_name) df,
(select round(sum(bytes)/(1024*1024)) totalusedspace, tablespace_name
from dba_segments
group by tablespace_name) tu
where df.tablespace_name = tu.tablespace_name;
create a Global Temporary Table which stores the data then store the data in this table using above query

Create a view, it'll do what you are expecting from this procedure.
You cannot just have a select statement in a PL/SQL block without an INTO clause and variable.
You could also create a Refcursor as an OUT paramter

Related

An equivalence of ".schema sqlite_master" in Oracle

I'm trying to do the same exercise for both SQLite and Oracle. In SQLite, there is a table sqlite_master containing a description of all of the other tables, indexes, triggers, and views that are contained within the database. I can see the query to generate sqlite_master with .schema sqlite_master.
In Oracle, the data dictionary is presented to us in the form of a number of views (DBA, ALL or USER). Let's take the table USER_TABLES as an example. We can do query on USER_TABLES, for example
SELECT table_name
FROM USER_TABLES;
Is there anyway to get the query used to create the table USER_TABLES in Oracle? I tried
SELECT dbms_metadata.get_ddl('TABLE', 'USER_TABLES')
FROM dual;
but it does not work.
I am not sure what are you looking for but if you want the definition of any table in oracle you can use :
Describe TableName
Or if you want to have list of tables, views or columns you can use below queries:
For Tables :
select * from select * from all_tables
For Columns :
select * from all_tab_columns
For Views :
select * from select * from all_views
To get all the column information of a table:
select *
from all_tab_columns
where upper(table_name) = upper('Test')
order by column_id
Typically oracle stores table_name in uppercase so I used upper() or you can just type 'TEST'
You could use this one:
DECLARE
DDL CLOB;
BEGIN
FOR aTab IN (SELECT TABLE_NAME FROM USER_TABLES) LOOP
DDL := DBMS_METADATA.GET_DDL('TABLE', aTab.TABLE_NAME);
DBMS_OUTPUT.PUT_LINE(DDL);
END LOOP;
END;
You may customize the output with DBMS_METADATA.SET_TRANSFORM_PARAM() before you run the query.

Trying to conversion a view from oracle to PostgreSQL getting error relation "sys.dba_data_files" does not exist

CREATE OR REPLACE VIEW vtot_space (tablespace_name, tbytes)
AS
SELECT tablespace_name, sum(bytes) as tbytes
FROM sys.dba_data_files
group by tablespace_name
order by 1;
In postgress, to find the tablespace and its size you need following query:
SELECT spcname as tablespace_name,
pg_size_pretty(pg_tablespace_size(spcname)) as tbytes
FROM pg_tablespace;

SQL Procedure to Return Counts of All Unique IDs in Some Tables within a Schema

I want to write a stored procedure that grabs all of the tables in a schema that have a column called "ID" , once I have those tables I want to output the counts of unique IDs within each table.
ex.
table1
table2
Output:
I have the latter portion implemented but the first part I'm having difficulties with. Here's my script so far:
create or replace PROCEDURE get_id_counts
IS
BEGIN
FOR table_n in (SELECT * FROM dba_tables) LOOP
EXECUTE IMMEDIATE 'SELECT ID, COUNT(*) FROM MySchema.' || table_n.table_name || ' GROUP BY ID';
END LOOP;
END;
/
execute get_id_counts;
Currently I receive the error : "%s: invalid identifier", I assume this is caused by the fact that not all of the tables in the schema have the column "ID"
Assuming that your database is Oracle
Use the dba_tab_columns to get only those which has ID column
So extend your query from
SELECT * FROM dba_tables
to
SELECT * FROM dba_tables where table_name in (select table_name from dba_tab_columns where column_name = 'ID');

PL/SQL Add Multiple Columns to Query with Single Function

Is there any way to accomplish something like this in PL/SQL...
select a.col1, a.col2, a.col3, myFunc(a.id) from myTable a;
and the result be more than 4 columns? So basically, is there a way for a function to return or pipe more than one column back? The number needed is known and set in stone, it's 3. So this query would return 6 columns. I know I could call the myFunc() 3 separate times but the amount of processing would be tripled.
I've been playing around with pipeline functions but it doesn't appear they can be used to do this.
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit
Production PL/SQL Release 11.2.0.2.0 - Production
Thanks!
Here are ways to do it in various Oracle versions. I use DBA_OBJECTS only as a substitute for your real table.
CREATE OR REPLACE TYPE my_func_rec IS OBJECT
(
mf_col1 NUMBER,
mf_col2 NUMBER,
mf_col3 NUMBER
);
CREATE OR REPLACE TYPE my_func_tab IS TABLE OF my_func_rec;
CREATE OR REPLACE FUNCTION my_func (id NUMBER)
RETURN my_func_tab IS
l_result my_func_tab;
BEGIN
SELECT my_func_rec (id + 100, id + 101, id + 102)
BULK COLLECT INTO l_result
FROM DUAL;
RETURN l_result;
END my_func;
12c
In 12c, it's pretty simple using CROSS APPLY.
SELECT object_id,
object_type,
status,
mf_col1,
mf_col2,
mf_col3
FROM dba_objects o
CROSS APPLY (SELECT mf_col1,
mf_col2,
mf_col3
FROM TABLE (my_func (o.object_id)) odet);
11g
In 11g, you do not have access to CROSS APPLY so you need to select the function results as an object and then TREAT it as an object to get access to the individual fields.
SELECT object_id,
object_type,
status,
TREAT (val AS my_func_rec).mf_col1,
TREAT (val AS my_func_rec).mf_col2,
TREAT (val AS my_func_rec).mf_col3
FROM (SELECT object_id,
object_type,
status,
(SELECT my_func_rec (mf_col1, mf_col2, mf_col3)
FROM TABLE (my_func (o.object_id)) mf)
val
FROM dba_objects o)
NOTE: I created the 11g answer after the 12c answer. The 11g answer can be further simplified by having my_func return a my_func_rec instead of a my_func_tab. In this case, it would simplify to:
SELECT object_id,
object_type,
status,
TREAT (val AS my_func_rec).mf_col1,
TREAT (val AS my_func_rec).mf_col2,
TREAT (val AS my_func_rec).mf_col3
FROM (SELECT object_id,
object_type,
status,
my_func (o.object_id) val
FROM dba_objects o)
A very simplied illustration. Hope it helps.
--The best way here is to make a table type function
--as mentioned below
--Create object type
CREATE OR REPLACE TYPE OBJ_DUM
IS
OBJECT
(
COL1 NUMBER,
COL2 NUMBER,
COL3 VARCHAR2(100) );
/
--Create table type
CREATE OR REPLACE TYPE TAB_DUM
IS
TABLE OF OBJ_DUM;
/
--Create dummy function. This canbe a pipelined function also
CREATE OR REPLACE
FUNCTION SO_DUM
RETURN TAB_DUM
AS
lv_tab tab_dum:=tab_dum(NULL,NULL,NULL);
BEGIN
SELECT obj_dum(level,level+1,'AVRAJIT+'
||LEVEL) BULK COLLECT
INTO lv_tab
FROM DUAL
CONNECT BY LEVEL < 2;
RETURN lv_tab;
END;
/
--To check the output
SELECT TAB.*,OBJ.* FROM USER_OBJECTS OBJ,TABLE(SO_DUM) TAB;

how to write multiple select queries in one procedure body

this is my pl/sql code for oracle 11g XE. how can i fix this i want to run both select queries at one time help me please....they are work as single procedures.
CREATE OR REPLACE PACKAGE myproc
as
PROCEDURE TestProc (p_recordset OUT SYS_REFCURSOR, lock_s OUT SYS_REFCURSOR);
END myproc;
/
CREATE OR REPLACE PACKAGE BODY myproc
IS
PROCEDURE TestProc (p_recordset OUT SYS_REFCURSOR, lock_s OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_recordset FOR
select a.TABLESPACE_NAME as Tablespace,
round((1-((a.BYTES-nvl(b.BYTES,0))/a.BYTES))*100,2) AS Percentages
from (select TABLESPACE_NAME, sum(BYTES) BYTES
from sys.dba_data_files
group by TABLESPACE_NAME) a,
(select TABLESPACE_NAME, sum(BYTES) BYTES
from sys.dba_free_space
group by TABLESPACE_NAME) b
where a.TABLESPACE_NAME = b.TABLESPACE_NAME (+)
order by ((a.BYTES-b.BYTES)/a.BYTES) desc;
SELECT vh.sid locking_sid,
vw.sid waiter_sid,
vs.status status,
vs.program program_holding,
vsw.program program_waiting
FROM v$lock vh, v$lock vw, v$session vs, v$session vsw
WHERE (vh.id1, vh.id2) IN (SELECT id1, id2
FROM v$lock
WHERE request = 0
INTERSECT
SELECT id1, id2
FROM v$lock WHERE lmode = 0)
AND vh.id1 = vw.id1
AND vh.id2 = vw.id2
AND vh.request = 0
AND vw.lmode = 0
AND vh.sid = vs.sid
AND vw.sid = vsw.sid;
end;
end;
/
The error message is :-
Warning: Package Body created with compilation errors.
SQL> show error
Errors for PACKAGE BODY MYPROC:<br/>
LINE/COL ERROR
-------- -----------------------------------------------------------------
13/4 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
The error means that you are SELECTing some data, but not doing anything with it. I suspect you want to put this data into your lock_s procedure parameter, which is presently unused. In such case, all you need to do is to add the line
OPEN lock_s FOR
immediately above the second query. (You've managed this with p_recordset for the first one, I'm not sure why you haven't for the second one.)
If you have a SELECT statement in a procedure, you need to do something with the results.
If you know that you are fetching exactly one row, you can do a SELECT INTO one or more local variables.
If you are selecting multiple rows, you can do a SELECT BULK COLLECT INTO a collection or set of collections that you have defined.
You can use the SELECT statement to open a cursor that you either return from your stored procedure (as a SYS_REFCURSOR output parameter) or that you loop through in your procedure.
Incidentally, unless you have some need to be backward compatible with ancient versions of Oracle, the second query is going to be far more self-explanatory if you use the dba_waiters view rather than joining to v$lock twice.