trying to get total sales for a specific zip; I have done a couple of these, but cant seem to get the total and I'm missing something.
Tables are Customers that has the zip,
sales that has the gross sale amount.
This one executes complete but no total; so what am I missing?
Also for the sake of asking how could I modify this to ask me in an interface, where I can input the zip? I started that too but; again, I get the question when I insert the zip it gives me errors.
SET SERVEROUTPUT ON
DECLARE
V_SALES NUMBER (10,2);
V_ZIP VARCHAR2(5) NOT NULL := 48228;
BEGIN
SELECT SUM(S.GROSS_SALE_PRICE) -- GROUP FUNCTION
INTO V_SALES
FROM SALES S
WHERE CUST_ID = V_ZIP;
DBMS_OUTPUT.PUT_LINE ('TOTAL SALES FOR ZIP 48228, IS'|| TO_NUMBER(V_SALES));
END;
/
Try including a group by clause
SET SERVEROUTPUT ON
DECLARE
V_SALES NUMBER (10,2);
V_ZIP VARCHAR2(5) NOT NULL := 48228;
BEGIN
SELECT SUM(S.GROSS_SALE_PRICE) -- GROUP FUNCTION
INTO V_SALES
FROM SALES S
WHERE CUST_ID = V_ZIP
GROUP BY CUST_ID;
DBMS_OUTPUT.PUT_LINE ('TOTAL SALES FOR ZIP 48228, IS'|| TO_NUMBER(V_SALES));
END;
Related
This is sql block i'm using in Oracle,
Now I need to do the same way in Teradata, Is possible? I want the syntax FOR UPDATE CURSOR in Teradata!
Can you please guide me?
declare
cursor c1 is select * from Employees FOR UPDATE;
a number :=0 ;
begin
for x in c1 loop
a := a +1 ;
update employees set salary = a where current of c1;
end loop;
end;
Updateable cursors are allowed in ANSI-mode sessions only.
The syntax is quite similar:
declare c1 cursor for
select * from Employees FOR UPDATE;
a number :=0 ;
begin
for x in c1 loop
a := a +1 ;
update employees set salary = a where current of c1;
end loop;
end;
But cursors perform really bad in a parallel DBMS like Teradata as they're processed serially, one row after the other.
In almost every case cursors on data can be rewritten set-based (e.g. your example is a simple ROW_NUMBER) and then they perform several orders of magnitude faster.
Maybe you could use this instead?
UPDATE employees
FROM (
SELECT csum(1,1) new_salary, emp_id
FROM employees
) src
set salary=src.new_salary
where employees.emp_id=src.emp_id;
I would like to know if there's any option to iterate a table while performing SELECT values into a CURSOR.
For example:
I have a table TEMP_NUMBERS which contains only numbers (single column).
I have to perform a SELECT from each number in the table (I do not know the amount of rows in the table in advance).
Here is basically what I'm attempting to do. Obviously this does not work, but can I do some kind of a workaround?
I need to SELECT the data into the p_cv_PermsNotifs which is a RETURN REF CURSOR.
IF NOT p_cv_PermsNotifs%ISOPEN THEN OPEN p_cv_PermsNotifs FOR
FOR i IN 1..TEMP_NUMBERS.NUMBER.COUNT LOOP
SELECT DISTINCT
SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM
SEC_USER_ROLE
WHERE
SEC_USER_ROLE.ENTITY_ID = i
END LOOP;
END IF;
Also tried this:
IF NOT p_cv_PermsNotifs%ISOPEN THEN OPEN p_cv_PermsNotifs FOR
SELECT DISTINCT
SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM
SEC_USER_ROLE
WHERE
SEC_USER_ROLE.ENTITY_ID IN
(SELECT * FROM TABLE (lv_ListOfEntities))
END IF;
Where lv_ListOfEntities is table of NUMBER indexed by BINARY INTEGER.
But I'm getting "ORA-22905: cannot access rows from a non-nested table item"
Thanks in advance.
In> Hey if you pass a single number at a time, everytime the refcursor
will be overwritten by the next value. So at the end you will only get
the value for last number in the refcursor. A better way is to use
some basic PL/SQL Bulk COLLECT logic which will give you the desired
output.
Hope this helps
--Creating sql type
CREATE OR REPLACE TYPE lv_num_tab IS TABLE OF NUMBER;
--plsql block
var p_lst refcursor;
DECLARE
lv_num lv_num_tab;
BEGIN
SELECT COL1 BULK COLLECT INTO lv_num FROM TEMP_NUMBERS;
OPEN p_lst FOR
SELECT DISTINCT SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM SEC_USER_ROLE
WHERE SEC_USER_ROLE.ENTITY_ID IN
(SELECT * FROM TABLE(cast(lv_num as lv_num_tab))
);
END;
--Student(id, company) Table schema
create or replace procedure student_update(
v_company IN VARCHAR2(10),
v_id IN NUMBER
)
IS
BEGIN
update student set company=v_company where id=v_id;
commit;
END student_update;
/
Error: Encountered the symbol '(' where expecting one of the following
Need to change the dataType of the parameters
create or replace procedure student_update(
v_company IN student.company%TYPE,
v_id IN student.id%TYPE
)
IS
BEGIN
update student set company=v_company where id=v_id;
END;
/
This works fine.
You cannot give a length to you parameters. If you really need to limit v_company to 10, you can do a length check inside the procedure.
You might also consider looking into using Native Dynamic SQL. You're at risk running code straight from inputs.
CREATE OR REPLACE PROCEDURE student_update
(
v_company IN VARCHAR2
,v_id IN NUMBER
) IS
BEGIN
IF LENGTH(v_company) > 10 THEN
raise_application_error(-20001, 'Company must be 10 Char or less.');
END IF;
UPDATE student SET company = v_company WHERE ID = v_id;
COMMIT;
END student_update;
/
This question was asked in one practical exams at my university.
Q: A table has following columnheads/columns:
medicine_name,medicine_manufacture_date,medicine_expiry_date.
As the columnhead names describe they have the respective data about a medicine in them.
Now they asked to write a pl/sql block to make list of all medicines' names which have expired(i.e.current system date is greater than the expirydate values of the medicine).
I strongly think that the column of sequential consecutive integers(like 1,2,3,...n) must be added to the table, which will act as a primary key to each medicine name.Medicine names are unique but to perform iterative operations they should posses an integer primary key.
Is it still possible to get the result without assigning an ineteger primary key?
I altered the table and assigned primary key to each record and wrote following block... It worked
but i want to do it without assigning a primary key. All possible smart ways will be adored!Plz suggest correction of any type in my code... My code is as follows:
declare
a date;
b date;
diff number(10);
medicine varchar(25);
begin
a:=sysdate;
for i in 1..5
loop
select medicine_expiry_date into b from med_details where med_id=i ;
diff:=trunc(a-b);
if
diff>0 then
select medicine_name into medicine from med_details where med_id=i;
dbms_output.put_line(medicine);
end if;
end loop;
end;
/
Try
BEGIN
DBMS_OUTPUT.PUT_LINE('The following medicines have expired:');
FOR aRow IN (SELECT MEDICINE_NAME
FROM MEDICINE
WHERE EXPIRY_DATE < SYSDATE)
LOOP
DBMS_OUTPUT.PUT_LINE(aRow.MEDICINE_NAME);
END LOOP;
END;
You could put an artificial primary key on this table if there was some need to have some other table refer to this one and no other practical candidate key was available, but it's not needed to answer the question as asked above.
Share and enjoy.
It looks straightforward... I suspect that there are some extra details.
/*
Q: A table has following columnheads/columns:
medicine_name,
medicine_manufacture_date,
medicine_expiry_date.
Now they asked to write a pl/sql block to make list of all medicines' names which have expired
(i.e.current system date is greater than the expirydate values of the medicine).
*/
-- SQL:
SELECT medicine_name
FROM a_table
WHERE medicine_expiry_date < SYSDATE;
-- PL/SQL v.1:
DECLARE
TYPE medicine_ntt IS TABLE OF a_table%ROWTYPE;
l_medicine medicine_ntt;
BEGIN
SELECT medicine_name
, medicine_expiry_date
BULK COLLECT INTO l_medicine
FROM a_table;
FOR indx IN 1..l_medicine.COUNT LOOP
IF l_medicine(indx).medicine_expiry_date < SYSDATE THEN
DBMS_OUTPUT.PUT_LINE(l_medicine(indx).medicine_name);
END IF;
END LOOP;
END;
-- PL/SQL v.2:
DECLARE
CURSOR medicine_cur IS
SELECT medicine_name
, medicine_expiry_date
FROM a_table;
TYPE medicine_ntt IS TABLE OF medicine_cur%ROWTYPE;
l_medicine medicine_ntt;
l_medicine_expired medicine_ntt := medicine_ntt();
BEGIN
OPEN medicine_cur;
FETCH medicine_cur BULK COLLECT INTO l_medicine;
CLOSE medicine_cur;
FOR indx IN 1..l_medicine.COUNT LOOP
IF l_medicine(indx).medicine_expiry_date < SYSDATE THEN
l_medicine_expired.EXTEND;
l_medicine_expired(l_medicine_expired.LAST) := l_medicine(indx);
END IF;
END LOOP;
FOR indx IN 1..l_medicine_expired.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(l_medicine_expired(indx).medicine_name);
END LOOP;
END;
I am writing the procedure as
create or replace procedure my_proc(limit_value in number,.........)
is
cursor...................
.........................
begin
open ...;
loop
.....
.....
close ....;
end my_proc;
I want to generate the reports who are having the salary less than limit value.
Is it possible to get the table records with OUT parameter to generate the reports?
If it is possible, please explain
Yes, you can. You can even do it with the return value of the procedure / function:
create or replace type salary_rec as object (
emp_id number
salary number
);
create or replace type t_salary as table of salary_rec;
create or replace function retrieve_emp(
i_max_salary number
) return t_varchar_number
as
result t_salary;
begin
select salary_rec(emp_id, salary) bulk collect into result
from emp_salary
where salary <= i_max_salary;
return ret;
end;
/
That's just one of many variations of BULK COLLECT and of the different table types in Oralce and PL/SQL.