function in plsql - sql

I have created this function and it works:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
if
(p_ssnr is not null and p_password is not null) then
v_number:= 1;
else
v_number:= 0;
end if;
return v_number;
end;
If I then type: select log_in('social security number','the password') from dual; then I get a "1"
so it works. But you could basically type whatever you want and it will work so it is not a clean code. Since you can't include subquery in the if statement, how can you create the function so you only return 1 when you actually type a social security number (ssnr) and a password that matches the actual customer table? and otherwise you return 0?

NOt sure if you can have multiple rows for same customer. If yes, then use this:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
select case when count(*) > 0 then 1 else 0 end
into v_number
from customer
where ssnr = p_ssnr and password = p_password;
return v_number;
end;
If not then this should be fine:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
count(*)
into v_number
from customer
where ssnr = p_ssnr and password = p_password;
return v_number;
end;

Related

PL/SQL: SQL Statement ignored with oracle function

I try to compile the function but they show the error "PL/SQL: SQL Statement ignored" and mention the function "PO_PROD_CODE".
Could you please help to give some comment.
PL/SQL: SQL Statement ignored with oracle function (Function "PO_PROD_CODE")
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2) RETURN VARCHAR2 IS
v_po_prod_code_result VARCHAR2(100);
BEGIN
SELECT FLEX_VALUE
INTO v_po_prod_code_result
FROM apps.FND_FLEX_VALUES_VL
WHERE attribute1 IN ('BXX', 'EXX', 'GXX', 'HKXX', 'PDX', 'PSX', 'GPX')
AND FLEX_VALUE = s_prod_code ;
RETURN v_po_prod_code_result;
END;
/
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER) RETURN VARCHAR2 IS
v_po_doc_location_text VARCHAR2(150);
s_prod_code VARCHAR2(20);
BEGIN
SELECT 'PO\'||PO_DIVISION_CODE||'\'||PO_PRODUCT_LINE||'\'||PO_NUM||'\' AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE (SELECT ffvv.attribute1 bs_group
FROM apps.fnd_flex_values_vl ffvv,
apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ((ffvv.attribute4 = 'Y' AND poh.ORG_ID = 83) OR (ffvv.attribute5 = 'Y' AND poh.ORG_ID = 87))
AND ffvv.flex_value = PO_PROD_CODE (v_po_prod_code_result, s_prod_code) --call the "PO_PROD_CODE" function get the sql feild "prod_line_code")
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh
WHERE poh.ORG_ID = N_ORG_ID
AND poh.po_header_id = N_PO_HEADER_ID
);
EXCEPTION
WHEN OTHERS THEN
v_po_doc_location_text := 'PO\MO\';
END;
RETURN v_po_doc_location_text + s_prod_code;
END;
Complie success!
When I try to run the script, the detail as follow:
SELECT abc.XXX_util.PO_DOC_LOCATION_TEXT ('83','1145225') from dual;
The error message said
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
It is not FROM ... INTO, but INTO ... FROM:
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2) RETURN VARCHAR2 IS
v_po_prod_code_result VARCHAR2(100);
BEGIN
SELECT FLEX_VALUE
FROM apps.FND_FLEX_VALUES_VL --> this is
INTO v_po_prod_code_result --> wrong
WHERE attribute1 IN ('BXX', 'EXX', 'GXX', 'HKXX', 'PDX', 'PSX', 'GPX')
AND FLEX_VALUE = s_prod_code ;
RETURN v_po_prod_code_result;
END;
/
Should be
SELECT FLEX_VALUE
INTO v_po_prod_code_result
FROM apps.FND_FLEX_VALUES_VL
[EDIT]
The second function's CASE is invalid. That SELECT should be moved out of it, its tables used in main SELECT's FROM clause. Something like this (which is OK in syntax, I don't know whether it'll work):
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER)
RETURN VARCHAR2
IS
v_po_doc_location_text VARCHAR2 (150);
BEGIN
SELECT 'PO\'
|| PO_DIVISION_CODE
|| '\'
|| PO_PRODUCT_LINE
|| '\'
|| PO_NUM
|| '\'
AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE ffvv.attribute1
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END
PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh,
apps.fnd_flex_values_vl ffvv,
apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ( ( ffvv.attribute4 = 'Y'
AND poh.ORG_ID = 83)
OR ( ffvv.attribute5 = 'Y'
AND poh.ORG_ID = 87))
AND ffvv.flex_value =
PO_PROD_CODE (v_po_prod_code_result, s_prod_code)
AND poh.ORG_ID = N_ORG_ID
AND poh.po_header_id = N_PO_HEADER_ID);
RETURN v_po_doc_location_text;
EXCEPTION
WHEN OTHERS
THEN
v_po_doc_location_text := 'PO\MO\';
END;
There are several errors in your code and you'll have to correct them all:
You're supposed to write the SELECT INTO statement by writing the INTO part before writing the FROM (as you have written in your PO_DOC_LOCATION_TEXT function)
Your WHEN-THEN comparisons are missing the CASE word
In your PO_DOC_LOCATION_TEXT function you have called your PO_PROD_CODE function by passing two parameters, but it only accepts one parameter. You should only pass input parameter. If you want to fill local variable with the returning value from PO_PROD_CODE function, you should do it outside of SQL query.
You are missing one ) bracket in your query inside PO_DOC_LOCATION_TEXT function and I guess it's the one that got lost inside your call the "PO_PROD_CODE" function get the sql feild "prod_line_code" comment
You're ending your PO_DOC_LOCATION_TEXT function before the RETURN statement. You should add one more BEGIN before your SELECT INTO
I can also see that your PO_PROD_CODE function (as it's now written) always returns the input value (s_prod_code).
It's selecting fnd_flex_values_vl.flex_value into return variable just after saying that the very same flex_value must be equal to s_prod_code, which is your function's input parameter.
I guess this is the way you intended your code to be like:
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2)
RETURN VARCHAR2
IS
v_po_prod_code_result VARCHAR2 (100);
BEGIN
SELECT flex_value
INTO v_po_prod_code_result
FROM apps.fnd_flex_values_vl
WHERE attribute1 IN ('BXX',
'EXX',
'GXX',
'HKXX',
'PDX',
'PSX',
'GPX')
AND flex_value = s_prod_code; -- STILL JUST RETURNS THE INPUT PARAMETER
RETURN v_po_prod_code_result;
END;
/
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER)
RETURN VARCHAR2
IS
v_po_doc_location_text VARCHAR2 (150);
s_prod_code VARCHAR2(20); -- NEEDS TO HAVE SOME VALUE ASSIGNED BEFORE PASSING IT TO "PO_PROD_CODE" FUNCTION BELOW IN CODE
BEGIN
BEGIN
SELECT 'PO\' || PO_DIVISION_CODE || '\' || PO_PRODUCT_LINE || '\' || PO_NUM || '\' AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE (SELECT ffvv.attribute1 bs_group
FROM apps.fnd_flex_values_vl ffvv, apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ( (ffvv.attribute4 = 'Y' AND poh.ORG_ID = 83) OR (ffvv.attribute5 = 'Y' AND poh.ORG_ID = 87))
AND ffvv.flex_value = PO_PROD_CODE (s_prod_code) --call the "PO_PROD_CODE" function get the sql feild "prod_line_code", "v_po_prod_code_result" removed because PO_PROD_CODE expects only one parameter and because only input parameters can be written here
)
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END
PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh
WHERE poh.ORG_ID = N_ORG_ID AND poh.po_header_id = N_PO_HEADER_ID);
EXCEPTION
WHEN OTHERS
THEN
v_po_doc_location_text := 'PO\MO\';
END;
RETURN v_po_doc_location_text;
END;
I hope I helped!

ORACLE SQL PASSWORD FUNCTION

Need to create a function that verifies a password (more than 5 characters, different from the previous one, it isn't neither "password" nor "123456")
I tried this but i get errors
CREATE OR REPLACE FUNCTION my_verification_function (
username VARCHAR2,
password VARCHAR2,
old_password VARCHAR2)
RETURN BOOLEAN IS
BEGIN
IF LENGTH(password) < 6 THEN RETURN FALSE;
ELSE IF (password = "password" OR password = '123' OR password = old_password) THEN RETURN FALSE
ELSE RETURN TRUE;
END IF;
END my_verification_function;$
CREATE OR REPLACE FUNCTION my_verification_function (
username VARCHAR2,
pass VARCHAR2,
old_password VARCHAR2)
RETURN varchar2 IS
BEGIN
IF LENGTH(pass) < 6 THEN RETURN 'FALSE';
ELSIF (pass = 'password' OR pass = '123456' OR pass = old_password) THEN RETURN 'FALSE';
ELSE RETURN 'TRUE';
END IF;
END;
Several notes:
1) You should use ELSIF instead of ELSE IF
2) If you need call this function in "pure" SQL, BOOLEAN type will give you error, so you can use VARCHAR2 instead.
3) Don't use reserved words like PASSWORD
It should be done like this:
CREATE OR REPLACE FUNCTION my_verification_function (
username VARCHAR2, password VARCHAR2, old_password VARCHAR2)
RETURN BOOLEAN AS
BEGIN
IF LENGTH(password) < 6 THEN
RETURN FALSE;
ELSIF (password = "password" OR password = '123' OR password = old_password) THEN
RETURN FALSE
ELSE
RETURN TRUE;
END IF;
END my_verification_function;
/
alter profile default limit password_verify_function my_verification_function;
Parameter name USERNAEM and PASSWORD seems to be no problem, since Oracle provided default function (located in ORACLE_BASE/ORACLE_HOME/RDBMS/ADMIN/UTLPWDMG.SQL) uses them also.

PL/SQL Function for Correct Shipping Address

I am trying to make a PL/SQL function that when given the customer number looks to see if the order was sent to the customer address. If the customer's address matches the order address then the function needs to return True. This is what I came up with but I can't get it to work. Any help would be appreciated.
CREATE OR REPLACE Function CorrectAddress
(aCustNo IN Customer.CustNo%TYPE) RETURN VARCHAR IS
aCustStreet Customer.CustStreet%TYPE;
aCustCity Customer.CustCity%TYPE;
aCustState Customer.CustState%TYPE;
aOrdStreet OrderTbl.OrdStreet%TYPE;
aOrdCity OrderTbl.OrdCity%TYPE;
aOrdState OrderTbl.OrdState%TYPE;
RightAdd VARCHAR;
BEGIN
SELECT Customer.CustStreet, Customer.CustCity, Customer.CustState OrderTbl.OrdStreet, OrderTbl.OrdCity, OrderTbl.OrdState
INTO aCustStreet, aCustCity, aCustState, aOrdStreet, aOrdCity, aOrdState
FROM Customer, OrdertTbl
WHERE Customer.CustNo = OrderTbl.CustNo;
IF aCustStreet = aOrdStreet AND aCustCity = aOrdCity AND aCustState = aOrdState THEN RightAdd := True;
ELSE RightAdd := False;
END IF;
END;
Try this one, why did you want to return 'varchar', is it your custom type? if you want to return true/false you have to come with 'boolean', also you need to check whether you have rows in the table, for that you need to put exception handler
`CREATE OR REPLACE Function CorrectAddress
(aCustNo IN Customer.CustNo%TYPE) RETURN boolean IS
aCustStreet Customer.CustStreet%TYPE;
aCustCity Customer.CustCity%TYPE;
aCustState Customer.CustState%TYPE;
aOrdStreet OrderTbl.OrdStreet%TYPE;
aOrdCity OrderTbl.OrdCity%TYPE;
aOrdState OrderTbl.OrdState%TYPE;
`BEGIN
SELECT
Customer.CustStreet,
Customer.CustCity,
Customer.CustState,
OrderTbl.OrdStreet,
OrderTbl.OrdCity,
OrderTbl.OrdState
INTO
aCustStreet,
aCustCity,
aCustState,
aOrdStreet,
aOrdCity,
aOrdState
FROM
Customer,
OrdertTbl
WHERE Customer.CustNo = OrderTbl.CustNo;`
`IF aCustStreet = aOrdStreet AND aCustCity = aOrdCity AND aCustState = aOrdState THEN
return true;
ELSE
return false;
END IF;`
`Exception
when no_data_found then
return false;`
`END;`
why not do something in these lines, much cleaner to read and why use all these fields when they are not needed (haven't tested the plsql block, but for the general idea check below);
declare
V_COUNTER number := 0;
V_RESULT boolean;
begin
select
count('x')
into
V_COUNTER
from
Order o
inner join Customer c on c.Street = o.Street and
c.City = o.City and
c.State = o.State
where
o.Orderid = 100100;
if V_COUNTER = 0 then
V_RESULT := False;
else
V_RESULT := True;
end if;
end;

Updating a record in database

Using TADOCommand to update a record.
using TADOCommand to insert a new record.
Name of table is Board
Using MS Access database
I get an error
Syntax error in UPDATE/INSERT INTO statement
I can connect and retrieve data just fine. Just never added or updated data before.
My database columns looks like this
ID (auto number)
SN (text)
CardType (text)
Desc (memo)
dbDate (date)
Tech (text)
Code looks like this:
procedure TForm2.BSaveClick(Sender: TObject);
const
sqlStringNew = 'INSERT INTO Board (SN,CardType,Desc,dbDate,Tech) VALUES (:aSN,:aCardType,:aDesc,:aDate,:aTech);';
sqlStringUpdate = 'UPDATE Board SET SN=:aSN, CardType=:aCardType, Desc=:aDesc, dbDate=:aDate, Tech=:aTech WHERE ID = :aID;';
var
ADOCommand : TAdoCommand;
begin
ADOCommand := TADOCommand.Create(nil);
// updating a board
if NewBoard = false then
begin
try
ADOCommand.Connection := adoConnection1;
ADOCommand.Parameters.Clear;
ADOCommand.Commandtext := sqlStringUpdate;
ADOCommand.ParamCheck := false;
ADOCommand.Parameters.ParamByName('aSN').Value := ESerialNumber.Text;
ADOCommand.Parameters.ParamByName('aCardType').Value := ECardType.Text;
ADOCommand.Parameters.ParamByName('aDesc').Value := MDescription.Text;
ADOCommand.Parameters.ParamByName('aDate').Value := strtodate(EDate.Text);
ADOCommand.Parameters.ParamByName('aTech').Value := ETech.Text;
ADOCommand.Parameters.ParamByName('aID').Value := UpdateID;
ADOCommand.Execute;
finally
ADOCommand.Free;
end;
Showmessage('Update Complete');
end;
//if a new board
if NewBoard = True then
Begin
try
ADOCommand.Connection := adoConnection1;
ADOCommand.Parameters.Clear;
ADOCommand.Commandtext := sqlStringNew;
ADOCommand.ParamCheck := false;
ADOCommand.Parameters.ParamByName('aSN').Value := ESerialNumber.Text;
ADOCommand.Parameters.ParamByName('aCardType').Value := ECardType.Text;
ADOCommand.Parameters.ParamByName('aDesc').Value := MDescription.Text;
ADOCommand.Parameters.ParamByName('aDate').Value := strtodate(EDate.Text);
ADOCommand.Parameters.ParamByName('aTech').Value := ETech.Text;
ADOCommand.Execute;
finally
ADOCommand.Free;
end;
NewBoard := false;
BSave.Enabled := false;
NoEdit;
Showmessage('New Record Added');
End;
end;
It is advisable not to use SQL keywords for table and field names. DATE is a function in many SQL dialects. If you choose to use a reserved word/function name for a table/field name, you have to escape it in SQL statement: [Date] for SQL Server and MS Access, "Date" - for Oracle.

Why isn't my authentication working? (Apex)

I have a function to authenticate my users, which works because I tested it.
Authenticate function:
create or replace function authenticate(p_username in VARCHAR2, p_password in VARCHAR2)
return BOOLEAN
is
l_password varchar2(4000);
l_stored_password varchar2(4000);
l_count number;
begin
select count(*) into l_count from users where username = p_username;
if l_count > 0 then
-- First, we fetch the stored hashed password
select password into l_stored_password
from users where upper(username) = upper(p_username);
-- we have to apply the custom hash function to the password
l_password := custom_hash(p_username, p_password);
-- Finally, we compare them to see if they are the same and return
-- either TRUE or FALSE
if l_password = l_stored_password then
return true;
else
return false;
end if;
else
-- The username provided is not in the users table
return false;
end if;
end;
Yet my authentication in Apex doesn't work, I activated the authentication scheme and linked to authenticate function.
I'm using apex 4.2
This is how I've got mine setup:
Scheme Type: Custom
Authentication Function Name: my_auth_func
Source:
FUNCTION my_auth_func (p_username IN VARCHAR2, p_password IN VARCHAR2)
RETURN BOOLEAN
IS
is_authenticated BOOLEAN := FALSE;
BEGIN
--authentication logic, etc...
RETURN is_authenticated;
END