Getting multiple values from a function - oracle11g

I have my CLIENTS table with the fields: (PK:ID NUMBER), PRICE NUMBER, PAYMENT_TYPE_ID NUMBER, SESSION_AREA NUMBER
I created a dynamic action from my page, in order to take the above values from CLIENTS table according to my :P2007_CLIENTS_ID.
First i created this type:
CREATE OR REPLACE EDITIONABLE TYPE "PATIENT_DETAILS" as object
( payment_type number,
session_area number,
price number
)
/
then i created this function:
create or replace FUNCTION "F_PATIENT_DETAILS"
(patient_id in NUMBER, session_date date)
RETURN patient_details
IS
v_payment_type number;
v_session_area number;
v_price number;
BEGIN
SELECT CLIENTS.PAYMENT_TYPE_ID into v_payment_type
FROM CLIENTS
WHERE CLIENTS.ID = patient_id;
SELECT CLIENTS.SESSION_AREA into v_session_area
FROM CLIENTS
WHERE CLIENTS.ID = patient_id;
SELECT CLIENTS.PRICE into v_price
FROM CLIENTS
WHERE CLIENTS.ID = patient_id;
if v_price is null then
SELECT POLICIES.PRICE into v_price
FROM POLICIES
WHERE POLICIES.ACTIVE = 1
AND to_char(session_date, 'MM-DD-YYYY') BETWEEN POLICIES.START_DATE AND POLICIES.END_DATE;
end if;
return patient_details(v_payment_type, v_session_area, v_price);
END;
How do i get the values from this function in my page, with Dynamic Action?
I tried this: Identification-> Set Value, Set Type -> PL/SQL Function Body:
declare
My_Result PATIENT_DETAILS;
begin
My_Result := F_PATIENT_DETAILS(:P2007_CLIENTS_ID, :P2007_SESSION_DATE);
end;
Items to Submit-> P2007_CLIENTS_ID, :P2007_SESSION_DATE
Affected Elements -> P2007_PAYMENT_TYPE_ID, :P2007_SESSION_AREA, :P2007_PRICE
but nothing happens..!

Those three fields are never assigned the new values after your function is returned, eg:
:P2007_PAYMENT_TYPE_ID := my_result.payment_type;
Also, there is no reason for 3 separate queries on CLIENTS. You could do this in one motion.
SELECT c.PAYMENT_TYPE_ID, c.SESSION_AREA, c.PRICE
into v_payment_type, v_session_area, v_price
FROM CLIENTS c
WHERE c.ID = patient_id;
Taking that a step further, you could coalesce c.price with a subquery on policies.
Which has a questionable filter on a date being represented as a character. I doubt this would return accurate results.

Related

MariaDB Stored Procedure store paramters for update

I am trying to write a MariaDB stored procedure.
Due to SQL_SAFE_UPDATES, it is required to use the ID column to use in the WHERE clause for updates. Due to this, what is the normal approach to also select a value from one of the other columns? I do not want to have multiple SELECT statements as it seems inefficient and room for error because they could return values from different rows.
I would like to store my first select statement
SELECT id, sequence FROM RECORDSEQUENCE WHERE SEQTABLE = SeqTable;
In the following two parameters #id, #seq from two seperate columns in the above query and use them in the UPDATE statement as well as the IF statement.
CREATE DEFINER=`sd`#`%` PROCEDURE `SD_GenerateNextRecordSequence`(IN SeqTable int)
BEGIN
SELECT id, sequence FROM RECORDSEQUENCE WHERE SEQTABLE = SeqTable;
IF (#seq IS NOT NULL) THEN
SET #NEXTSEQ := #seq+1;
UPDATE RECORDSEQUENCE SET RECORDSEQUENCE = #NEXTSEQ WHERE id = #id;
ELSE
SET #NEXTSEQ := 100;
INSERT INTO RECORDSEQUENCE (RECORDSEQUENCE,SEQTABLE) VALUES (#NEXTSEQ,SeqTable);
END IF;
SELECT #NEXTSEQ as SEQUENCE;
END

Creating a Database Trigger that checks if more than one record was added on a date?

CREATE OR REPLACE TRIGGER POSITION_NUMBER
BEFORE UPDATE OR INSERT OR DELETE ON APPLIES
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
NUMBER_OF_POSITIONS NUMBER;
BEGIN
SELECT count(pnumber) INTO NUMBER_OF_POSITIONS
FROM APPLIES WHERE anumber = :NEW.anumber;
IF( NUMBER_OF_POSITIONS > 2 AND count(APPDATE) > 2 )
THEN
RAISE_APPLICATION_ERROR(-20000,'an Employee cannot apply for
more than two positions');
END IF;
END;
/
Im attemtping to create a trigger that goes off if an Applicant applys for more than two Positions on the Same Day, but im not sure how i would implement the Date side of it. Below is the set of relational Schemeas
You can use the TRUNC function to remove the time portion and then see if the application date matches today's date, regardless of time.
Also, there is no need for the autonomous transaction pragma. You are not executing any DML.
CREATE OR REPLACE TRIGGER position_number
BEFORE UPDATE OR INSERT OR DELETE
ON applies
DECLARE
number_of_positions NUMBER;
BEGIN
SELECT COUNT (pnumber)
INTO number_of_positions
FROM applies
WHERE anumber = :new.anumber AND TRUNC (appdate) = TRUNC (SYSDATE);
IF number_of_positions > 2
THEN
raise_application_error (
-20000,
'An Employee cannot apply for more than two positions on the same day');
END IF;
END;
/

Search for field name in access table then update relevant fields names with values delphi 7

I have an Access database table named ReceiptTable with the following field names: item name, buying price, selling price, goods total, cash, change. I am using an Adoquery and datasource to connect to the access database. When I want to update records to receiptTable, I use the following code to locate an item name from the database then update all the records with similar item name in the database with the values from edit box field values:
procedure TReceiptForm.BitBtn1Click(Sender: TObject);
begin
with ADOQuery1 do
ADOQuery1.Open;
ADOQuery1.Locate('item name',Edit1.Text,[]) ;
ADOQuery1.edit;
ADOQuery1.FieldValues['goods total']:=edit3.Text;
ADOQuery1.FieldValues['cash']:=edit4.Text;
ADOQuery1.FieldValues['change']:=edit5.Text;
ADOQuery1.Post;
end;
The problem I have is that only one row with the item name is updated but the other rows with similar item name are not updated. What code should I add above so that all the rows which have similar item names are updated with values from edit boxes?
This simple code answers your question:
procedure TReceiptForm.BitBtn1Click(Sender: TObject);
var
itemname, goodstotal, cash, change: string;
begin
// Execute query
try
ADOQuery1.Open;
except
on E: Exception do begin
ShowMessage(E.Message);
Exit;
end{on};
end{try};
// Values
itemname := Edit1.Text;
goodstotal := Edit3.Text;
cash := Edit4.Text;
change := Edit5.Text;
// Find first matching record, then go to the end of resultset.
try
ADOQuery1.DisableControls;
if ADOQuery1.Locate('item name', itemname, []) then begin
while not ADOQuery1.Eof do begin
if ADOQuery1.FieldByName('item name').AsString = itemname then begin
ADOQuery1.Edit;
ADOQuery1.FieldValues['goods total'] := goodstotal;
ADOQuery1.FieldValues['cash'] := cash;
ADOQuery1.FieldValues['change'] := change;
ADOQuery1.Post;
end{if};
ADOQuery1.Next;
end{while};
end{if};
finally
ADOQuery1.EnableControls;
end{try};
end;
This will work, but you can consider using one SQL statement for updating the table, or
if it is possible order your query by 'item name' and use this:
...
// Find first matching record, then update while next record matches too.
if ADOQuery1.Locate('item name', itemname, []) then begin
while (not ADOQuery1.Eof) and
(ADOQuery1.FieldByName('item name').AsString = itemname) do begin
ADOQuery1.Edit;
ADOQuery1.FieldValues['goods total'] := goodstotal;
ADOQuery1.FieldValues['cash'] := cash;
ADOQuery1.FieldValues['change'] := change;
ADOQuery1.Post;
ADOQuery1.Next;
end{while};
end{if};
...

PL/SQL Function_get total balance has errors

I was trying to create a function that given a customer name, get the total balance of that customer's accounts from the account table(A#, CNAME, BAL).
When compiling in command, I got errors:
line "SELECT SUM(bal) INTO total_a_bal FROM account" ignored
and line "WHERE account.cname = v_acname" SQL cmd not properly ended.
Please help correct the errors. Any help would be greatly appreciated!
My function is :
CREATE OR REPLACE FUNCTION totbal
(v_acname IN account.cname%type)
RETURN NUMBER
IS
total_a_bal NUMBER;
BEGIN
SELECT SUM(bal) INTO total_a_bal FROM account
group by account.cname
WHERE account.cname = v_acname;
RETURN total_a_bal;
END;
/
This may not be the only problem with your function, but the WHERE clause always precedes the GROUP BY clause in a SQL query. Hence, your function should look like this:
CREATE OR REPLACE FUNCTION totbal
(v_acname IN varchar2) -- a type should follow IN, e.g. varchar2
RETURN NUMBER
IS
total_a_bal NUMBER;
BEGIN
SELECT SUM(bal) INTO total_a_bal
FROM account
WHERE account.cname = v_acname; -- WHERE always precedes GROUP BY
GROUP BY account.cname
RETURN total_a_bal;
END;
Oracle not only works with the parameter definition "account.cname%type" that is preferred method. What it does is to bind the parameter definition to the column in the database. If the column definition is changed the procedure automatically gets the changed.
This concept of defining in terms of data base columns can (and perhaps should) be extended into the variables and return types of the procedure/function itself.
This function then becomes:
CREATE OR REPLACE FUNCTION totbal
(v_acname IN account.cname%type)
RETURN account.bal%type
IS
total_a_bal account.bal%type;
BEGIN
SELECT SUM(bal) INTO total_a_bal FROM account
group by account.cname
WHERE account.cname = v_acname;
RETURN total_a_bal;
END;

oracle pl sql function having errors

I want to create a function that returns the number of rows in a table called Rating with a where clause.Where am i going wrong before the declare statement and the end statement?
create or replace
FUNCTION get_movies(user IN NUMBER) RETURN NUMBER
IS
DECLARE cnt NUMBER;
BEGIN
SELECT count(*)
INTO cnt
FROM rating
where userid= user;
RETURN cnt;
END;
I will appreciate help.Thanks.
You should not have the DECLARE keyword. You only need that for an anonymous block (or a sub-block).
create or replace
FUNCTION get_movies(p_userid IN NUMBER) RETURN NUMBER
IS
cnt NUMBER;
BEGIN
...
user is a reserved word so I'd suggest not using that as your parameter name. In the where clause I'm not sure if it will use your parameter value, or the name of the user executing the function; which would error as that string value couldn't be implicitly converted to a number.

Resources