Exit from stored procedure in sybase - sybase-ase

I am getting some parameters in my stored procedure. Before operating on these parameters, I want to validate them and if the parameters are not as per the requirement then I want to exit from the stored procedure with an error message.
sample code:
create proc abcd
(
zip varchar(20),
name varchar(20),
network varchar(1)
)
-- validation section
IF (len(zip)<>5 OR LEN(zip)<>9)
begin
print "The zip must be of 5 or 9 characters"
<---- how to exit from here--->
end
IF (len(name)<2)
begin
print "The name must be of at least 2 characters"
<---- how to exit from here--->
end
---- main code
How can I exit the procedure once I get the error as mentioned above?

You can use return command as below
-- validation section
IF (len(zip)<>5 OR LEN(zip)<>9)
begin
print "The zip must be of 5 or 9 characters"
return 1
end
IF (len(name)<2)
begin
print "The name must be of at least 2 characters"
return 2
end
return 0 -- on the end of procedure
to catch the result you can use this code:
declare #ProcResult int
execute #ProcResult = abcd #Zip = ..., #name...
select #ProcResult

Let me suggest a few changes:
create procedure abcd
#zip varchar(20),
#name varchar(20),
#network varchar(1)
AS
-- validation section
IF (len(#zip)<>5 AND LEN(#zip)<>9)
begin
-- print "The zip must be of 5 or 9 characters"
raiserror 20000 "The zip must be of 5 or 9 characters"
return 1
end
IF (len(#name)<2)
begin
-- print "The name must be at least 2 characters"
raiserror 20001 "The name must be at least 2 characters"
return 2
end
There are numerous options with raiserror but this should point you in the right direction.
Edit: added return statements

Related

using nested table as in Parameter to a Procedure

I have a table T1 and I want to insert multiple rows at a time through a procedure using collection. I have written the code but when I'm trying to execute it throws an error. Please advise.
create table t1 ( id number , name varchar2(10));
/
create or replace PACKAGE PKG1 AS
TYPE TAB_LIST IS TABLE OF T1%ROWTYPE;
PROCEDURE PROC1 (p_val IN TAB_LIST);
END PKG1;
/
create or replace PACKAGE BODY PKG1 AS
PROCEDURE PROC1 (P_VAL IN TAB_LIST
)
IS
BEGIN
FOR i IN p_val.FIRST..p_val.LAST
LOOP
insert INTO T1
(
id, name
)
VALUES
(
p_val(i).id,
p_val(i).name
);
END LOOP;
END;
END;
error after executing
DECLARE
p_val PKG1.TAB_LIST;
BEGIN
p_val := PKG1.TAB_LIST(123,'XYZ');
END;
Error report -
ORA-06550: line 5, column 11:
PLS-00306: wrong number or types of arguments in call to 'TAB_LIST'
ORA-06550: line 5, column 11:
PLS-00306: wrong number or types of arguments in call to 'TAB_LIST'
ORA-06550: line 5, column 2:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
DECLARE
P_VAL PKG1.TAB_LIST := PKG1.TAB_LIST();
BEGIN
P_VAL.extend;
P_VAL(1).id := 123;
P_VAL(1).name := 'XYZ';
PKG1.PROC1( P_VAL );
END;
example for multiple records:
DECLARE
P_VAL PKG1.TAB_LIST := PKG1.TAB_LIST();
BEGIN
for i in 1 .. 10
loop
P_VAL.extend;
P_VAL(P_VAL.LAST).id := i;
P_VAL(P_VAL.LAST).name := 'XYZ' || i;
end loop;
PKG1.PROC1( P_VAL );
END;
#hekko": its not a string .sorry about formatting . The multiple values (n) can be passed from application like this and all should be inserted into table at once.
123 'XYZ'
456 'DFK'
866 'HKK'
#Kaushik :it is not a string but formatting issue.. the question remains the same "I have a table T1 and I want to insert multiple rows at a time through a procedure using collection.

I create one PL/SQL procedure i want simple show two messages?

The PL/SQL procedure below:
'DECLARE
V_EMPNO NUMBER(10):=&EMPNO;
V_EMPNO2 NUMBER(10):= 0;
CURSOR C1 IS SELECT EMPNO FROM EMP;
BEGIN
FOR I IN C1 LOOP
FETCH C1 INTO V_EMPNO2;
EXIT WHEN C1%FOUND;
END LOOP;
IF (LENGTH(V_EMPNO)) > 4 THEN
DBMS_OUTPUT.PUT_LINE ('LENGTH OF EMPNO GREATER THAN 4 NUMBER');
ELSIF (V_EMPNO = V_EMPNO2) THEN
DBMS_OUTPUT.PUT_LINE ('THIS EMPLOYEE NUMBER ALREADY EXIST');
END IF;
END;
/'
In this procedure I want show two messages
one is if lenght greater than number 4 than show message
and second is if v_empno = v_empno2 then show second message
empno = v_empno then show message:
DBMS_OUTPUT.PUT_LINE ('THIS EMPLOYEE NUMBER ALREADY EXIST')
this is error
Enter value for empno: 4444
DECLARE
*
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at line 7
I think there are a couple of problems with your code.
C1 does not restrict on employee number (meaning the loop will
return a single, largely random row from table emp
You are mixing FOR LOOP and FETCH syntax
Variable v_empno is a NUMBER and you need to be careful when checking the length - you need to explicitly TO_CHAR and control the format - often TO_CHAR will end up including space characters (an alternative would be to check the value of a number is < 10000)
I've not tested this code but this might be closer to what you're after :
DECLARE
l_empno NUMBER := &empno ;
CURSOR C_get_emp
IS
SELECT e.empno
FROM emp e
WHERE e.empno = l_empno
;
R_emp C_get_emp%ROWTYPE ;
BEGIN
IF LENGTH(TRIM(TO_CHAR(l_empno))) > 4 THEN
DBMS_OUTPUT.put_line('Length of empno > 4') ;
ELSE
OPEN C_get_emp ;
FETCH C_get_emp INTO R_emp ;
IF C_get_emp%FOUND THEN
DBMS_OUTPUT.put_line('Employee number already exists') ;
END IF ;
CLOSE C_get_emp ;
END IF ;
END ;
FOR I IN C1 LOOP
already implicitly opens c1 and handles the fetching, so your explicit fetch after it is invalid.
btw i is normally used for numeric indexes rather than records.
Also your caps lock was on when you wrote that code ;)

How to query only numbers from string in MySQL

I have a MySQL query and need to ask for a field which contains the ZIP code. Unfortunately some people enter also the city name or suburb into the ZIP field. I was looking for a query code which would return only the numbers from the field. Any code I already found on stackoverflow producec errors for me besides the following: How to remove all non-alpha numeric characters from a string?
This code however only deletes no alphanumeric characters. What would be the correct code to also remove all a,b,c characters.
Thank you for helping
UPDATE: The code posted by Syed Noman works for me in phpmyadmin.
However when I add this to my query in my php code I get a parsing error.
Here is the code which produces the error.
$query = "DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
DECLARE i, len SMALLINT DEFAULT 1;
DECLARE ret CHAR(32) DEFAULT '';
DECLARE c CHAR(1);
IF str IS NULL
THEN
RETURN "";
END IF;
SET len = CHAR_LENGTH( str );
REPEAT
BEGIN
SET c = MID( str, i, 1 );
IF c BETWEEN '0' AND '9' THEN
SET ret=CONCAT(ret,c);
END IF;
SET i = i + 1;
END;
UNTIL i > len END REPEAT;
RETURN ret;
END |
DELIMITER ;
SELECT digits(`asdf`) FROM `12345` WHERE 1 ";
The error indicates a problem with the last ";"
USE REGEXP for getting only numbers
SELECT *
FROM your_table
WHERE zipcode REGEXP '^[0-9]+$';
or
SELECT *
FROM your_table
WHERE zipcode > 0
Hope it will help
expected output
Your zipcode column contains
123
145adb
adds142
157
237
output will be
123
157
237

ORA-06502: PL/SQL: numeric or value error: character string buffer too small, when PLSQL called

I've started getting the below error since I added o_ID to the procedure, everything worked fine until I added in o_ID, is it to do with o_ID being set as the wrong data type possibly? I've looked through any other related topics on SO but to no avail.
o_ID is being initially set like below before PR_LOAD_XML_FILEis called:
$id = 0;
$stmt->bindParam('o_ID', $id);
From the Logs
2015-12-18T13:02:06+00:00 ERR (3): An exception occurred while executing 'BEGIN PR_LOAD_XML_FILE (
i_XML => :i_XML,
i_FILENAME => :i_FILENAME,
o_ID => :o_ID,
on_ErrorID => :on_ErrorID
);
END;' with params ["<?xml version=\"1.0\" encoding=\"UTF-8\" ?><test><TestDetails><TestVersionId>3244<\/TestVersionId><Marks>20<\/Marks><\/TestDetails><\/test>", "test.csv"]:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 1
Procedure Spec
PROCEDURE PR_LOAD_XML_FILE (
i_XML IN CLOB,
i_FILENAME IN XML_DOC.FILENAME%TYPE,
o_ID OUT NUMBER,
on_ErrorID OUT INTEGER
);
Procedure Body
PROCEDURE PR_LOAD_XML_FILE (
i_XML IN CLOB,
i_FILENAME IN XML_DOC.FILENAME%TYPE,
o_ID OUT NUMBER,
on_ErrorID OUT INTEGER
) IS
doc_id XML_DOC.id%TYPE;
xml XMLTYPE;
BEGIN
...
END PR_LOAD_XML_FILE;
I think when you're calling your procedure, you are setting the variable to receive the value of o_ID as string. Here's my package that mocks yours:
CREATE OR REPLACE PACKAGE PKG_PR_LOAD_XML_FILE
AS
PROCEDURE PR_LOAD_XML_FILE (
i_XML IN CLOB,
i_FILENAME IN varchar2,
o_ID OUT NUMBER,
on_ErrorID OUT INTEGER );
END PKG_PR_LOAD_XML_FILE;
/
CREATE OR REPLACE PACKAGE BODY PKG_PR_LOAD_XML_FILE
AS
PROCEDURE PR_LOAD_XML_FILE (
i_XML IN CLOB,
i_FILENAME IN varchar2,
o_ID OUT NUMBER,
on_ErrorID OUT INTEGER )
IS
BEGIN
dbms_output.put_line( 'i_XML: '||i_XML );
dbms_output.put_line( 'i_FILENAME: '||i_FILENAME );
o_ID := 999999;
on_ErrorID := 123456789;
END PR_LOAD_XML_FILE;
END PKG_PR_LOAD_XML_FILE;
/
In SQL*Plus I will first define these two bind variables. Notice how bind variable v_o_ID is set to varchar2(4). This is meant to fail because the value of o_ID is set to 999999 in the procedure, which is longer than 4 characters (If the value of o_ID was set to 9999, which is 4 characters or less, then the procedure call would have worked fine, but the bug would still be there, and would creep up on you as soon as the value of o_ID would get bigger than 4 characters):
SQLPlus> var v_o_ID varchar2(4)
SQLPlus> var v_on_ErrorID number
Now I am calling the procedure in SQL*Plus, and it'll fail:
SQLPlus> exec PKG_PR_LOAD_XML_FILE.PR_LOAD_XML_FILE( '<heres my XML>', 'heresfilename.csv', :v_o_ID, :v_on_ErrorID);
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 1
Now I will set bind variable v_o_ID to number, and the procedure call will be success. You can see the received values from the procedure if you print the bind variables using print command:
SQLPlus> var v_o_ID number
SQLPlus> exec PKG_PR_LOAD_XML_FILE.PR_LOAD_XML_FILE( '<heres my XML>', 'heresfilename.csv', :v_o_ID, :v_on_ErrorID);
i_XML: <heres my XML>
i_FILENAME: heresfilename.csv
PL/SQL procedure successfully completed.
SQLPlus> print v_o_ID
V_O_ID
----------
999999
SQLPlus> print v_on_ErrorID
V_ON_ERRORID
------------
123456789

Why am I getting an Ada error?

This is, as you could tell, a programming assignment for a class. It's far over due and I'm not getting any points however there is a test coming up soon and I'd rather like to know how to use the specific functions in ADA. The program is different now, when I run it with test put statements in the initial procedure, GetStudent, it will output them fine. However now it goes to the bottom, line 96, and gets an end error
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Integer_Text_IO;
USE Ada.Integer_Text_IO;
WITH Ada.Float_Text_IO;
USE Ada.Float_Text_IO;
procedure StudentFileLab is
------------------------------------------------------------------------
--| This program stores records in an array, reading them in from a file
--| and writing them out.
------------------------------------------------------------------------
subtype NameType is String(1..30);
subtype IDType is natural range 0..9999;
subtype GPAType is float range 0.0..4.0;
type StudentRecord is record
ID : IDType;
GPA : GPAType;
Name : NameType := (others => ' ');
end record;
subtype StudentIndex is integer range 1..100;
TYPE StudentArrayType IS ARRAY (StudentIndex) OF StudentRecord;
-- Specification of input procedure. You are to write the body.
PROCEDURE GetStudent (File: IN File_Type; Student : OUT StudentRecord) is
Length : Integer;
BEGIN
For I In 0..Length Loop
Get(File, Student.ID);
For J In 0..Length Loop
Get(File, Student.GPA);
For K In 0..Length Loop
Get_Line (File, Student.Name, Length);
End Loop;
END LOOP;
End LOOP;
END GetStudent;
PROCEDURE PutStudent (Student : IN StudentRecord) IS
BEGIN
FOR Studentlist IN StudentIndex LOOP
Put (Student.ID,
width => 0);
Put (Item => " ");
Put (Student.GPA,
Exp => 0,
Fore=> 0,
Aft => 0);
Put (Item => ", ");
Put (Student.Name);
New_Line;
END LOOP;
END PutStudent;
StudentList : StudentArrayType; -- our array of students
CurrentIndex : Natural := 0; -- the index to the current array item
CurrentStudent : StudentRecord; -- the current student
Filename : String(1..30); -- name of the data file
Flength : Integer; -- length of the name of the data file
Infile : File_Type;
begin -- StudentLab
Put_Line(Item=>"Welcome to the Student Information Program.");
Put_Line(Item=>"Please enter the student filename: ");
Get_Line(Item=> Filename, Last => Flength);
Open(File => Infile, Mode => In_File, Name => Filename(1..Flength));
loop
-- Get the next student
GetStudent(File=> infile, Student => CurrentStudent);
exit when CurrentStudent.Id = 0;
CurrentIndex := CurrentIndex + 1;
StudentList(CurrentIndex) := CurrentStudent;
END LOOP;
close(file=>infile); -- close the data file after all data is read.
-- Output the header for the nicely formatted output.
FOR Index IN 1..CurrentIndex loop
PutStudent(Student => StudentList(Index));
end loop;
end StudentFileLab;
The Program is supposed to read from a file that looks like this.
1435 3.75 Jane Smith
2233 2.94 Robert Robertson
9634 3.86 Jennie Diver
4325 3.42 Matt Pratt
0
So, Line 96 is literally the end loop line.
FOR Index IN 1..CurrentIndex loop
PutStudent(Student => StudentList(Index));
-----> end loop;
I may be wrong but I feel like my main problem is now with the body of PutStudent seen here:
FOR Studentlist IN StudentIndex LOOP
Put (Student.ID,
width => 0);
Put (Item => " ");
Put (Student.GPA,
Exp => 0,
Fore=> 0,
Aft => 0);
Put (Item => ", ");
Put (Student.Name);
New_Line;
END LOOP;
I feel like it's the for line but I can't tell how to fix it.
You aren’t getting End_Error at line 96 of your program, but in the runtime library.
When I run your program, I get
raised ADA.IO_EXCEPTIONS.END_ERROR : a-tigeli.adb:96
which is in fact in Ada.Text_IO.Get_Line.
When I compile your program with all warnings on, I get
studentfilelab.adb:35:19: warning: "Length" may be referenced before it has a value
and, looking at the code, this is
PROCEDURE GetStudent (File: IN File_Type; Student : OUT StudentRecord) is
Length : Integer;
BEGIN
For I In 0..Length Loop <<<<<<<< line 35
Get(File, Student.ID);
For J In 0..Length Loop
Get(File, Student.GPA);
For K In 0..Length Loop
Get_Line (File, Student.Name, Length);
End Loop;
END LOOP;
End LOOP;
END GetStudent;
So, firstly, you would need to set a value for Length; but, more importantly, this procedure is supposed (judging by its name and the context) to read the data for one student, so what are you doing looping in the first place?
GetStudent needs work even after this (you mustn’t try to read anything after the 0 that ends the input data) and I think there are more problems, but that should do to be going on with.

Resources