when I am trying to create a log_in function?Why I have error Error(3,10): PLS-00215: String length constraints must be in range (1 .. 32767) - sql

I am trying to create a function to verify log_in by return 0(zero) if the login failed, or 1(one) if the login was successful by matching cust_id and Passwd as parametrars and I have two questions:
Why I get error bad bind p_cust_id?
How to return 0 when it fail?
.
create or replace function log_in
(
p_cust_id varchar2,
p_paswd varchar2
) return number
as p_all varchar2;
begin
select cust_id,passwd
into p_all
from customer
where cust_id=p_cust_id and passwd=p_paswd;
return 1;
end;

first of all, you are trying to select 2 column but into 1 variable. this can't be possible. check my fix below
select cust_id,passwd
into variable1, variable2
from customer
where cust_id=p_cust_id and passwd=p_paswd;
for your second requirement, you need to add below line before end.
EXCEPTION WHEN NO_DATA_FOUND THEN
return 0;
END;
EDIT
Your procedure can also be rewritten as
CREATE OR REPLACE FUNCTION LOG_IN
(
P_CUST_ID VARCHAR2,
P_PASWD VARCHAR2
) RETURN NUMBER
AS P_COUNT NUMBER;
BEGIN
SELECT COUNT(*)
INTO P_COUNT
FROM CUSTOMER
WHERE CUST_ID=P_CUST_ID AND PASSWD=P_PASWD;
IF (P_COUNT > 0)
RETURN 1;
END IF;
RETURN 0;
END;

Related

How to find rows that contain string in plsql function

When i try to implement the function to find if rows contain a string.
The function always return 0.
This is my function
member function containsText (pString1 varchar2, pString2 varchar2)return integer is
checked integer;
begin
if INSTR(pString2,pString1)=0 then checked := 0;
else checked := 1 ;
end if;
return checked;
end containsText;
i implement the function like below,
containsText (table_name.column_name, 'some_string_here');
it returns 0.
2 i try to find out why it doesn't work by using the code below,
containsText('abcdefg','fg');
it returns 0 as well.
i try instr method alone, it works
instr('abcdefg','fg');
it returns 6.
i use instr in query to implement my original idea
select instr(table_name.column_name,'Great') from table_name
it works. How could i make this function working as my expect?
Try
member function containsText (pString1 varchar2, pString2 varchar2)return integer is
checked integer;
begin
if INSTR(pString1, pString2)=0 then checked := 0;
else checked := 1 ;
end if;
return checked;
end containsText;
You change in INSTR(pString1, pString2)=0
You have the arguments to INSTR reversed. Also you have a MEMBER function but do not appear to be using any features that would require this. You could use:
Oracle Setup:
CREATE TYPE test_obj AS OBJECT(
value VARCHAR2(20),
MEMBER FUNCTION checkText(
self IN OUT test_obj,
match IN VARCHAR2
) RETURN NUMBER
);
/
CREATE TYPE BODY test_obj IS
MEMBER FUNCTION checkText(
self IN OUT test_obj,
match IN VARCHAR2
) RETURN NUMBER
IS
BEGIN
RETURN LEAST( INSTR( self.value, match ), 1 );
END;
END;
/
Testing:
DECLARE
v_test test_obj := test_obj( 'abcdefgh' );
BEGIN
DBMS_OUTPUT.PUT_LINE( v_test.checkText( 'gh' ) );
DBMS_OUTPUT.PUT_LINE( v_test.checkText( 'i' ) );
END;
/
Outputs:
1
0
db<>fiddle here
You could also write it without the SELF argument and taking two strings (as you've done in the question) but there does not seem to be much point of making this a MEMBER function of a type and it could just be a global stored-function or a STATIC function of the type.
CREATE TYPE test_obj AS OBJECT(
unused_value VARCHAR2(20),
MEMBER FUNCTION checkText( -- could be STATIC FUNCTION
value IN VARCHAR2,
match IN VARCHAR2
) RETURN NUMBER
);
/
CREATE TYPE BODY test_obj IS
MEMBER FUNCTION checkText( -- could be STATIC FUNCTION
value IN VARCHAR2,
match IN VARCHAR2
) RETURN NUMBER
IS
BEGIN
IF INSTR( value, match ) = 0 THEN
RETURN 0;
ELSE
RETURN 1;
END IF;
END;
END;
/
Then:
DECLARE
v_test test_obj := test_obj( 'xyz' );
BEGIN
DBMS_OUTPUT.PUT_LINE( v_test.checkText( 'abcdefgh', 'gh' ) );
DBMS_OUTPUT.PUT_LINE( v_test.checkText( 'abcdefgh', 'x' ) );
END;
/
Outputs:
1
0
db<>fiddle here

Using Functions in triggers

I have created a function,which i think is right but im not sure how to call it in the trigger. I know the trigger is wrong but thats what i have tried
Function:
create or replace function log_in(pass in varchar2, user in varchar2)
return number
is
match_count number;
begin
select count(*)
into match_count
from Member
where username=user
and password=pass;
return match_count;
end;
Trigger:
create or replace TRIGGER PASSWORDCHECK
BEFORE INSERT OR UPDATE ON Login
FOR EACH ROW
DECLARE
usern VARCHAR2(12);
pass VARCHAR2(12);
result number;
BEGIN
usern := :new.username;
pass := :new.password;
/*Select LOG_IN(pass,usern)INTO result From MEMBER Where usern = Username;*/
result := LOG_IN(pass,usern);
If result = 1 THEN
dbms_output.put_line('Login Succesful');
ElsIF result = 0 THEN
dbms_output.put_line('Login Failed');
END IF;
END;
I'm assuming all login attempts fail?
USER is a keyword, which identifies the current schema:
SQL> select user from dual;
USER
------------------------------
REF
As it's unlikely any of your users have the same name as the schema your count is always returning 0.

Can I have a function within a SELECT query?

Can I have a function within select statement like this?
select
myseq.nextval,
getDoctor(dbNumber,C.code,DOCCODE),
getDoctor(dbNumber,C.code,RFDOCCODE),
...
from charges c
where type='R';
Here getdoctor points to a function that checks two tables and returns a value:
create or replace function getDoctor(dbNumber IN NUMBER,code IN VARCHAR2(10),doccode IN VARCHAR2(10), OUT DOCID VARCHAR2(10))
is
begin
DOCID:= nvl((select MDOCID from NEW_PROVIDERS NP where dbNumber=NP.dbNumber and code=NP.code and doccode=NP.doccode),
select MDOCID from ProvidersProxy P where P.originalDB=dbNumber and code=P.originalGroup and doccode=P.originalDocCode);
return DOCID;
end getDoctor;
Write this (don't forget about the "p_" prefixes):
create or replace function getDoctor(
p_dbNumber IN NUMBER,
p_code IN VARCHAR2(10),
p_doccode IN VARCHAR2(10)
) return varchar2
is
l_DOCID VARCHAR2(10);
begin
begin
select MDOCID
into l_DOCID
from NEW_PROVIDERS NP
where p_dbNumber=NP.dbNumber
and p_code=NP.code
and p_doccode=NP.doccode
;
exception
when no_data_found then
select MDOCID
into l_DOCID
from ProvidersProxy P
where P.originalDB=p_dbNumber
and p_cpcode=P.originalGroup
and p_doccode=P.originalDocCode
;
end;
return l_DOCID;
end getDoctor;
The basic signature for an Oracle SQL usable function (which is well documented everywhere), is of the form:
FUNCTION my_function (param1 datatype, param2 datatype)
RETURN datatype
IS
local_variable1 datatype;
local_variable2 datatype;
BEGIN
-- Do something awesome
return local_variable;
/* Optional Exceptions Block */
END;
So in your case (with some rewriting of the NVL()) then:
create or replace function getDoctor(p_dbNumber IN NUMBER, p_code IN VARCHAR2, p_doccode IN VARCHAR2)
return varchar2
is
DOCID VARCHAR2(10);
begin
select MDOCID into DOCID
from NEW_PROVIDERS NP
where p_dbNumber=NP.dbNumber
and p_code=NP.code
and p_doccode=NP.doccode;
return DOCID;
EXCEPTION
when no_data_found then
select MDOCID INTO DOCID
from ProvidersProxy P
where P.originalDB=p_dbNumber
and p_code=P.originalGroup
and p_doccode=P.originalDocCode;
return DOCID;
end getDoctor;

PL SQL Function - How to call

I have a function in PL/SQL as follows (being used in Oracle APEX):
create or replace FUNCTION User_Levels(result OUT VARCHAR2)
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF v_user_types = 1
THEN
result := 'TRUE';
ELSE
result := 'FALSE';
END IF;
END User_Levels;​
How can I call this just to see its current output in normal SQL i.e. does it evaluate to True or False at the time it is run.
Do I really need the OUT parameter called result?
From SQL*Plus:
var result varchar2(10);
var rc varchar2(10);
exec :rc := user_levels(:result);
print rc
print result
However, your function is invalid because you have no return clause. Since the only thing you can return is result, having that as both an out parameter and the return value is redundant. Which you keep depends on how you want to use it, but I'd suggest a function is more flexible and appropriate here.
create or replace FUNCTION User_Levels
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF v_user_types = 1 THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
END User_Levels;​
/
... assuming v('APP_USER') does something sensible. You can then just do:
select user_levels from dual;
Should work. Typically, you would create a variable (like v_user_types) and return that (p_result). Also, you need to make sure that your v('APP_USER') is also uppercase.
Additionally, you can not run this from a SQL*PLUS or any command prompt as v('APP_USER') is application variable; therefore, you have to test this on an APEX page.
create or replace FUNCTION User_Levels(p_result OUT VARCHAR2)
RETURN VARCHAR2 IS
v_user_types employee.user_type%TYPE;
p_result VARCHAR2(10);
BEGIN
SELECT user_type
INTO v_user_types
FROM Employee
WHERE upper(username) = v('APP_USER');
IF (v_user_types = 1) THEN
p_result := 'TRUE';
ELSE
p_result := 'FALSE';
END IF;
RETURN p_result;
END User_Levels;​

PLS-00103 Oracle stored procedure error

I am new to stored procedures.
I am trying to run stored procedure and getting these errors:
I am getting PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: begin function pragma procedure...
PLS-00103: Encountered the symbol "RETURN" when expecting one of the following: * & = - + < / > at in is mod remainder not rem then...
I have tried searching for what causes these errors and for examples similar to this, but results were not sufficient. Any clues as to why these errors are happening?
here is the code:
CREATE OR REPLACE PROCEDURE LIST_ACTIONS_CHECK_ADD
(
LISTNAME IN VARCHAR2
) AS
BEGIN
DECLARE CNT NUMBER;
SELECT COUNT(LIST_NAME) INTO CNT FROM LISTS_MASTER WHERE LIST_NAME = LISTNAME;
IF (CNT > 0)
RETURN 1
ELSE
RETURN 0
END IF;
END LIST_ACTIONS_CHECK_ADD;
New Code:
CREATE OR REPLACE PROCEDURE LIST_ACTIONS_CHECK_ADD
(
P_LISTNAME IN VARCHAR2
)
AS
L_CNT NUMBER;
BEGIN
SELECT COUNT(LIST_NAME)
INTO L_CNT
FROM LISTS_MASTER
WHERE LIST_NAME = P_LISTNAME;
IF (L_CNT > 0)
RETURN 1;
ELSE
RETURN 0;
END IF;
END LIST_ACTIONS_CHECK_ADD;
The skeleton of a stored procedure declaration is
CREATE OR REPLACE PROCEDURE procedure_name( <<parameters>> )
AS
<<variable declarations>>
BEGIN
<<code>>
END procedure_name;
In the code you posted,
You put the BEGIN before the variable declarations
You have an extraneous DECLARE-- you would only use that if you are declaring a PL/SQL block that doesn't involve a CREATE.
You are missing semicolons after your RETURN statements.
A procedure cannot return a value. If you want to return either a 1 or a 0, you probably want a function, not a procedure. If you need a procedure, you can declare an OUT parameter.
You are missing the THEN after the IF
It sounds like you want something like
CREATE OR REPLACE FUNCTION LIST_ACTIONS_CHECK_ADD
(
LISTNAME IN VARCHAR2
)
RETURN NUMBER
AS
CNT NUMBER;
BEGIN
SELECT COUNT(LIST_NAME)
INTO CNT
FROM LISTS_MASTER
WHERE LIST_NAME = LISTNAME;
IF (CNT > 0)
THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END LIST_ACTIONS_CHECK_ADD;
Note that as a general matter, you are generally better off using some sort of naming convention to ensure that parameters and local variables do not share the name of a column. Trying to figure out whether LISTNAME is a parameter or a column name and what the difference between LIST_NAME and LISTNAME is will generally confuse future programmers. Personally, I use a p_ prefix for parameters and a l_ prefix for local variables. I would also suggested using anchored types-- lists_master.list_name%type if that is what is being passed in
CREATE OR REPLACE FUNCTION LIST_ACTIONS_CHECK_ADD
(
P_LIST_NAME IN lists_master.list_name%type
)
RETURN NUMBER
AS
L_CNT NUMBER;
BEGIN
SELECT COUNT(LIST_NAME)
INTO L_CNT
FROM LISTS_MASTER
WHERE LIST_NAME = P_LIST_NAME;
IF (L_CNT > 0)
THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END LIST_ACTIONS_CHECK_ADD;
(Correction #1) You cannot return a value in a procedure; LIST_ACTIONS_CHECK_ADD should be dropped and declared as a function in order to return a NUMBER
(Correction #2) You need to move the declaration of CNT as follows (see below)
(Correction #3) You need semicolons on the return statements:
(Correction #4) You need a THEN after IF (CNT > 0) (see below):
DROP PROCEDURE LIST_ACTIONS_CHECK_ADD;
CREATE OR REPLACE FUNCTION LIST_ACTIONS_CHECK_ADD
(
LISTNAME IN VARCHAR2
)
RETURN NUMBER AS
CNT NUMBER;
BEGIN
SELECT COUNT(LIST_NAME) INTO CNT FROM LISTS_MASTER WHERE LIST_NAME = LISTNAME;
IF (CNT > 0) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END LIST_ACTIONS_CHECK_ADD;
This Can be executed from SQLPLUS as:
SET SERVEROUTPUT ON SIZE 100000;
DECLARE
V_RESULT NUMBER;
BEGIN
V_RESULT := LIST_ACTIONS_CHECK_ADD('X');
DBMS_OUTPUT.PUT_LINE('RESULT: ' || V_RESULT);
END;