Select statement in PL/SQL - sql

Does anyone know how to use their tables and columns from pre-existing databases in a pl/sql command. I am using something from Oracles webpage to use as an example.
SQL> declare
2 v_line varchar2(40):= '&v_string';
3 begin
4 v_line := 'Hello '||v_line;
5 dbms_output.put_line (v_line);
6 end;
7 /
old 2: v_line varchar2(40):= '&v_string';
New 2: v_line varchar2(40):= 'Thomas';
Hello Thomas
PL/SQL procedure successfully completed.
I am wanting to be able to manipulate the data from above. Lets say I have a table called name_s and I have columns called n_first and n_last and I want to use those columns to output 'Hello Thomas' but using those tables.
I am new to pl.sql and trying to learn the syntax.
I wasn't sure if you could,
DECLARE
n_first
n_last
BEGIN
SELECT * FROM name_s
n_fisrt := 'Thomas'||n_first;
dbms_output.put_line(n_first)
END;
/
Desired Output: 'Thomas'
I understand that this is not syntactically correct but I am just trying to pick up on how you can use data from your existing tables to get this sort of desired output
EDIT: The above table is hypothetical and only contains two columns for this example. Now using real tables and data.
SET SERVEROUTPUT ON;
begin
for cur_r in (select loc_t from loc_t_matrix where store_s in(1,2,3,4,5); loop
dbms_output.put_line('Hello store' || cur_r.loc_traits );
end loop;
end;
/
The above does not compile

Do you need something like this
declare
v_authName author.author_last_name%type;
begin
select
author_last_name into v_authName
from
author
where
author_key = 'A103';
dbms_output.put_line('Name: '||v_authName);
end;
/
Name: weaton
http://www.dba-oracle.com/t_pl_sql_plsql_select_into_clause.htm

As tables usually contain more than one row, I presume that NAME_S also contains several rows. In that case, the simplest option to display those names is a cursor FOR loop (Google for it). For example:
begin
for cur_r in (select n_first, n_last from name_s) loop
dbms_output.put_line('Hello ' || cur_r.n_first ||' '||cur_r.n_last);
end loop;
end;
/
As you can see, you don't need local variables in that case.
If you used your SELECT ... INTO (as suggested by mCeviker), that would work unless it raises TOO-MANY-ROWS (as you can't put all rows' names into a single variable).

Related

Is there a way to loop through selected columns in plsql

I have a table TestTable with columns of col_test1, col_test2, col_test3 ...
and I want to create a loop that accesses each of these columns individually and find the max value and place it in the variable made in the declare block and simply dbms.out.put it.
Declare
my_array sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll('col_test1','col_test2','col_test2');
v_test number(8,0);
Begin
for r in my_array.first..my_array.last
loop
select max(my_array(r)) into v_test from TestTable;
dbms_output.put_line(v_test);
end loop;
End;
/
The output I get is just the string 'col_test1'which should be 50.
This is done through oracle SQL. Is there any way to achieve this?
You could use dynamic SQL for this
Declare
my_array sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll('col_test1','col_test2','col_test2');
v_test number(8,0);
Begin
for r in my_array.first..my_array.last
loop
execute immediate 'select max(' || my_array(r) || ') from TestTable'
into v_test;
dbms_output.put_line(v_test);
end loop;
End;
If you're going to resort to dynamic SQL, however, it would generally make more sense to build a single SQL statement that took that max of all three columns in one pass rather than potentially doing three separate table scans on the same table.

how to get multiple records by passing parameter to where clause in oracle pl/sql

table :
create table emp
(
E_ID number,
E_NAME varchar2(30)
);
select * from emp;
101 name1
102 name2
My code:
declare
v1 varchar2(30) := '101,102';
begin
for i in (select e_id,e_name
from emp
where e_id in (v1)) loop
dbms_output.put_line(i.e_id);
end loop;
end;
/
ISSUE:
Getting ORA -01722:invalid number
Please help to understand this issue and suggest me the solution.
It is syntax error.
E_ID is of number type and you are comparing it will v1 which is varchar2 type.
Welcome to SO. A great place to ask questions: I can see what you're trying to do. Syntactically, you'd be forgiven for trying to query your table using the "IN" clause, but as others have said, this can not be done where you have committed your numeric values into a varchar2. In anycase, an array or a collection, (even if you had created one) it isn't an easy option here. But you do have a variety of solutions open to you:
1/ Place your numbers into an Array and use a condition in your loop and check that e_id forms part of the your array. But in-elegant!
2/ Create a global temporary table and add your numbers in and add the table into your query, specify a join.
3/ Create some dynamic PL/SQL using a Ref Cursor. I've included an example for you below, using your table (emp) and values. In this case, you'd be able to build up your string according to the values you want to query. See below. The varchar2 string: sqlString can be manipulated however you want. Paste into a test-harness and see. Hope it helps
declare
type refCursor is ref cursor;
tableCursor refCursor;
emp_record emp%rowtype;
sqlString varchar2(200);
begin
-- Dynamic SQL statement with placeholder:
sqlString := 'SELECT * FROM emp WHERE e_id in
(101, 102)';
-- Open cursor:
open tableCursor for sqlString;
-- Fetch rows from result set one at a time:
loop
fetch tableCursor
into emp;
exit when tableCursor%notfound;
dbms_output.put_line(emp.e_id);
end loop;
-- Close cursor:
close tableCursor;
end;

Print multiple rows from select statement

I have this table :
| Pattern |
----------------------
|category |varchar|
|patternexpr |varchar|
For example in this table I can have a category ISBN and its pattern to recognize it.
I want to create a procedure which takes three arguments : a table T, one of its column C and a category. I want to print every rows in column C in T table which respect the pattern associated.
This is what I did (Updated with the correct answer):
CREATE OR REPLACE PROCEDURE Recognize(T varchar,C varchar,catego varchar)
IS
v_patt Pattern.CATEGOR%Type;
BEGIN
SELECT patternexpr INTO v_patt
FROM Pattern WHERE CATEGOR=catego;
FOR myrow IN (SELECT C FROM T WHERE REGEXP_LIKE(C, v_patt) LOOP
dbms_output.put_line(myrow.C);
END LOOP;
END;
/
How can I declare a cursor to print my result without knowing the value of my variable patt in the "DECLARE" place ? Should I add another declare and begin...end bloc after the first query ? What is the best way to do it ?
(I'm working on Oracle SGBD)
Use REF CURSOR to fetch records for this purpose.
CREATE OR REPLACE PROCEDURE Recognize(
T VARCHAR2,
C VARCHAR2,
catego VARCHAR2)
IS
v_patt Pattern.CATEGOR%Type;
v_cur_txt VARCHAR2(400);
TYPE cur_type
IS
REF
CURSOR;
v_cur cur_type;
v_c VARCHAR2(20);
BEGIN
SELECT patternexpr INTO v_patt FROM Pattern WHERE CATEGOR=catego;
v_cur_txt := 'SELECT '||C||' FROM '|| T ||' WHERE REGEXP_LIKE('||C||', '''||v_patt||''')';
OPEN v_cur FOR v_cur_txt;
LOOP
FETCH v_cur INTO v_c;
EXIT
WHEN v_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_c);
END LOOP;
CLOSE v_cur;
END;
/
NOTE: : Include proper EXCEPTION handling in your code for NO_DATA_FOUND etc.Also as per Nicholas , make some validations by using dbms_assert package
In Oracle, you don't need an explicit cursor:
for myrow in (select c from t where regexp_like(c, patt) loop
dbms_output.put_line(myrow.c);
end loop;
I would call the pattern variable something like v_patt; that way, declared variables don't get confused with column names.

How to output multiple rows from an existing table in a stored procedure using oracle sql developer?

I have an existing Customers table and want to output each row from this table using a stored procedure. There is no input criteria, just need to output all of the records.
The stored procedure should basically be equivalent to:
"SELECT C_ID, LAST, FIRST, DOB, DPHONE, EMAIL FROM customers;"
This seems simple but I can't figure it out. All my searches haven't worked out for this case.
How would one accomplish this?
EDIT: Answered my question below. Very simple.
In Oracle your options are:
1. Use a function and return a REF CURSOR
2. Use a procedure and use a REF CURSOR as an OUT parameter
3. Use a PIPELINED function
4. Use a function and return a collection.
read this documentation
Overview of Table Functions
see similar question here Return collection from packaged function for use in select
simple sample of such function
CREATE FUNCTION StockPivot(p refcur_pkg.refcur_t) RETURN TickerTypeSet
PIPELINED IS
out_rec TickerType := TickerType(NULL,NULL,NULL);
in_rec p%ROWTYPE;
BEGIN
LOOP
FETCH p INTO in_rec;
EXIT WHEN p%NOTFOUND;
-- first row
out_rec.ticker := in_rec.Ticker;
out_rec.PriceType := 'O';
out_rec.price := in_rec.OpenPrice;
PIPE ROW(out_rec);
-- second row
out_rec.PriceType := 'C';
out_rec.Price := in_rec.ClosePrice;
PIPE ROW(out_rec);
END LOOP;
CLOSE p;
RETURN;
END;
/
Nevermind! Just got it. It is pretty simple. I just did this:
CREATE OR REPLACE PROCEDURE CustomerReport AS
BEGIN
FOR cus IN (SELECT C_ID, LAST, FIRST, DOB, DPHONE, EMAIL FROM customers)
LOOP
dbms_output.put_line(cus.C_ID||' '||cus.FIRST||' '||cus.LAST||' '||cus.DOB||' '||cus.DPHONE||' '||cus.EMAIL);
END LOOP;
END;

oracle - mixing SQL code with PLSQL when no bindings in WHERE statement

I am trying to write a very simple sql script:
select * from table_X;
and I would like to see the results in oracle sqlplus, if there are any. These results are important for further analysis.
Also to mention, it depends, how many tables were created originally, so chances are that table_X may not be in the database at all. However I want to avoid getting an error, when parsing, that table_X doesn't exist, while running that script above.
So I was trying to wrap that SQL into some PLSQL dynamic code, like this:
Define table_X="MY_TAB"
DECLARE
stmt_ VARCHAR2(2000);
exist_ number := 0;
CURSOR table_exist IS
SELECT 1
FROM user_tables
WHERE table_name = '&table_X';
BEGIN
OPEN table_exist;
FETCH table_exist INTO exist_;
CLOSE table_exist;
IF exist_ = 1 THEN
stmt_ := 'SELECT * FROM &table_X';
EXECUTE IMMEDIATE stmt_;
ELSE
dbms_output.put_line('This functionality is not installed.');
END IF;
END;
/
Why I cannot see any result (records), if there is data in MY_TAB? Do I really need to bind some columns and use ex. dbms_output to be able to see some information?
Is there any simple way to query a table without getting 'ORA-00942: table or view does not exist'
if that table doesn't exist (ideally using SQL only)?
Thanks in advance
like this if you want it in sqlplus:
SQL> var c refcursor;
SQL> create or replace function get_table(p_tab in varchar2)
2 return sys_refcursor
3 is
4 v_r sys_refcursor;
5 NO_TABLE exception;
6 pragma exception_init(NO_TABLE, -942);
7 begin
8 open v_r for 'select * from ' || dbms_assert.simple_sql_name(p_tab);
9 return v_r;
10 exception
11 when NO_TABLE
12 then
13 open v_r for select 'NO TABLE ' || p_tab as oops from dual;
14 return v_r;
15 end;
16 /
Function created.
SQL> exec :c := get_table('DUAL2');
PL/SQL procedure successfully completed.
SQL> print c
OOPS
-----------------------------------------
NO TABLE DUAL2
SQL>
SQL> exec :c := get_table('DUAL');
PL/SQL procedure successfully completed.
SQL> print c
D
-
X
Instead of execute immediate 'query' you could use execute immediate 'query' bulk collect into and then loop over it and use dbms_output to print it.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm