T-SQL Function to Throw error - sql-server

Hello there I have a Function and is introduction a variable which will bring a letter or a number, if the variable is a letter it need to cause an error and return a 0, or if is a number then return 1.
SO in T-SQL I have a Procedure that eventually will call this function to check is is a number:
IF dbo.VALIDNUMBER(#sTxpX) != 0 AND #sTxpX IS NOT NULL
The variable #sTxpX is holding a value which is 'T' so I know it needs to return 0 from the function because is invalid to be a numeric, but Im not getting the proper function to build it, I will appreciate some help here.
CREATE FUNCTION DBO.VALIDNUMBER (#sTextStr VARCHAR(4000)) RETURNS BIT AS
BEGIN
DECLARE #bValidNumberStr BIT = 1; DECLARE #nTest BIGINT;
SET #nTest = CAST(#sTextStr AS numeric(38, 10)) + 1;
RETURN #bValidNumberStr;
EXCEPTION
WHEN OTHERS THEN
SET #bValidNumberStr = 0;
RETURN #bValidNumberStr;
END;

Try this function:
CREATE function [dbo].[VALIDNUMBER]
(#strText VARCHAR(4000))
RETURNS BIT
AS
BEGIN
DECLARE #Return as bit
IF TRY_CAST(#strText AS NUMERIC(38,10)) IS NOT NULL BEGIN
SET #Return = 1
END ELSE BEGIN
SET #Return = 0
END
RETURN #Return
END

Why can't you use the built-in SQL function? It's faster, and no need for you to drive yourself crazy to come up with a solution.
In your procedure do the following:
DECLARE #isNumber bit;
IF (ISNUMERIC(#sTextStr) = 1)
BEGIN
SET #isNumber = 1
END
ELSE
BEGIN
SET #isNumber = 0
RAISERROR(15600, 16, 20, 'That was not a number')
END
You can pass the #isNumber variable back to the user at a later point in time.

Related

Oracle function re-write in SQL-Server

I have an Oracle function that needs to be converted to SQL-Server function
This is the Oracle Function:
FUNCTION check_education(in_crs_code IN VARCHAR2)
RETURN BOOLEAN IS
v_bool BOOLEAN := FALSE;
v_dummy VARCHAR2(1);
CURSOR find_education IS
SELECT 'x'
FROM KU_LIBRARY_EDUCATION_EXTLOAN
WHERE UPPER(course_code) = UPPER(in_crs_code) AND in_use = 'Y';
BEGIN
OPEN find_education;
FETCH find_education INTO v_dummy;
IF find_education%FOUND THEN
v_bool := TRUE;
ELSE
v_bool := FALSE;
END IF;
CLOSE find_education;
RETURN (v_bool);
END check_education;
This is what I have written in SQL-Server to replicate Oracle function:
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000))
RETURNS BIT AS
BEGIN
DECLARE #v_bool BIT = 0;
DECLARE #v_dummy VARCHAR(1);
DECLARE find_education CURSOR LOCAL FOR
SELECT 'x'
FROM [dbo].[KU_LIBRARY_EDUCATION_EXTLOAN]
WHERE UPPER(course_code) = UPPER(#in_crs_code)
AND in_use = 'Y';
OPEN find_education;
FETCH find_education INTO #v_dummy;
IF ##CURSOR_ROWS >1 BEGIN
SET #v_bool = 1;
END
ELSE BEGIN
SET #v_bool = 0;
END
CLOSE find_education;
DEALLOCATE find_education;
RETURN (#v_bool);
END;
I would expect the SQL server function to return 1 if the cursor returns 'x' but i'm getting 0. Anu help will be appreciated.
I would suggest using an inline table valued function instead of a scalar function. To make sure this is an inline table valued function it MUST be a single select statement. This means there can't be loops and other stuff. Fortunately this query does not actually need any loops. A simple count will return the number of rows. And any value other than 0 when converted to a bit will always be 1.
CREATE FUNCTION [dbo].[check_education]
(
#in_crs_code VARCHAR(4000)
) RETURNS table as return
SELECT CourseExists = convert(bit, count(*))
FROM [dbo].[KU_LIBRARY_EDUCATION_EXTLOAN]
WHERE UPPER(course_code) = UPPER(#in_crs_code)
AND in_use = 'Y';
This is a mere EXISTS thing, so we could try
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000)) RETURNS BIT AS
BEGIN
RETURN EXISTS ( <query> )
END;
But as far as I know, SQL Server doesn't accept this (though I cannot say why not - maybe it's because of their lack of a real boolean; Oracle doesn't accept it, because EXISTS is no keyword in their PL/SQL programming language).
So we'd use IF/ THEN/ ELSE:
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000)) RETURNS BIT AS
BEGIN
IF EXISTS
(
SELECT 'x'
FROM ku_library_education_extloan
WHERE UPPER(course_code) = UPPER(in_crs_code) AND in_use = 'Y'
)
RETURN 1
ELSE
RETURN 0
END
END;
There may be errors, because I've never coded a stored procedure in T-SQL, but anyway, you get the idea.

Set parameter values according to other parameter value

I'm trying to setup parameter values according to other parameter value like following in stored procedure
DECLARE #secndvalues NCHAR(1);
IF (#firstvalue = 'Con')
BEGIN
SET #secndvalues = 'R';
END
ELSE IF (#firstvalue = 'Tin')
BEGIN
SET #secndvalues = 'N';
END
but it seems like it's not working with the second condition which is ELSE IF (#firstvalue = 'Tin'). How can I do this properly?
Your code should work, but a case seems simpler:
DECLARE #secndvalues NCHAR(1);
SET #secondvalues = (CASE WHEN #firstvalue = 'Con' THEN 'R'
WHEN #firstvalue = 'Tin' THEN 'N'
ELSE #secondvalues
END);
Actually problem was #firstvalue length too short keep its values, since that #firstvalue value getting null, therefor #secndvalues values can't setup , now problem sorted

How do i format a sql numeric type with commas on Sybase SQLAnywhere?

I came across the following solution but it does not work on Sybase
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
I have read the Convert Sybase information but still i receive the same number without the commas.
Have you tried giving a varchar (20) for example instead ? something like :
SELECT CONVERT(varchar(20), CAST(987654321 AS money), 1)
In SqlAnywhere money datatype is a domain, implemented as NUMERIC(19,4).
in CAST function , If you do not indicate a length for character string types, the database server chooses an appropriate length. If neither precision nor scale is specified for a DECIMAL conversion, the database server selects appropriate values.
So maybe this is what's causing the issue, what do you get as output ? do you get 987654321.00 , or just 987654321 ?
Update:
My last suggestion would be using insertstr() function and loop through the char value of your number to insert comma every 3 digits .. this is not the cleanest/easiest way but apparently SQLAnywhere deal with money datatype as normal NUMERIC datatype ...
insertstr() documentation is here.
I would give you a code sample but I don't have SQLAnywhere installed to test it ...
Here is the SP i created based on F Karam suggestion.
CREATE FUNCTION "DBA"."formattednumber"( in #number numeric)
returns char(60)
begin
declare #returnnumber char(60);
declare #workingnumber char(60);
declare #n_ind char(1);
declare #decimalnumber char(10);
declare #tempnumber char(60);
declare #decimalpos integer;
if isnull(#number,'') = '' then
return null
end if;
if #number < 0 then set #n_ind = 'Y'
else set #n_ind = 'N'
end if;
set #workingnumber = convert(char(60),ABS(#number));
set #decimalpos = patindex('%.%',#workingnumber);
if #decimalpos > 0 then
set #decimalnumber = substr(#workingnumber,#decimalpos);
set #decimalnumber = "left"(#decimalnumber,3+1);
set #workingnumber = "left"(#workingnumber,#decimalpos-1)
end if end if;
set #returnnumber = '';
while length(#workingnumber) > 3 loop
set #tempnumber = "right"(#workingnumber,3);
set #returnnumber = insertstr(0,#returnnumber,#tempnumber);
set #workingnumber = "left"(#workingnumber,length(#workingnumber)-3);
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,',')
end if
end loop;
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,#workingnumber)
end if;
if length(#decimalnumber) > 0 then
set #returnnumber = #returnnumber+#decimalnumber
end if;
if #n_ind = 'Y' then set #returnnumber = '-' || #returnnumber
end if;
return(#returnnumber)
end;
You need to distinguish between server-side and client-side formatting. When you use the 'isql' client for example (the TDS client), then the result will be this:
1> select convert(money, 9876543210)
2> go
9876543210
------------------------
9,876,543,210.00
(1 row affected)
But this is purely because the client application happens to format 'money' values this way. Also, this is actually not specific for SQLA, since isql is originally the client tool for ASE (a different Sybase database).
When you run the same conversion at the SQLA server (i.e. as part of an expression in a SQL statement), those commas will not be there since SQLA doesn't have such a built-in formatting style.
If you want this, you should write a SQL function that formats the number as you desire.

How to write these kind of functions in solr data config.xml

CREATE OR REPLACE FUNCTION page(IN i_app name character varying, IN i_photo_id big int, IN i_page integer, IN i_member_id big int, OUT o_similar_page_name character varying, OUT o_similar_page_id big int, OUT o_similar_photo_id big int[])
DECLARE
v_limit INTEGER := 4;
v_offset INTEGER;
BEGIN
SET SEARCH_PATH = '';
v_start_time = DAYTIME();
i_app name = UPPER(i_app name);
IF i_app name <> 'DD' THEN
RAISE EXCEPTION 'Enter Valid Application Name';
END IF;
IF i_page = 1 THEN
v_offset := 0;
ELSE
v_offset := i_page * v_limit - v_limit;
END IF;
Please help me.
Answer
No.
Reason
Its not actually the purpose of SOLR. Functions has to be written in the DB level and the data that is retrieved out of query will be stored in SOLR for fast retrieval.
ALTERNATIVE SOLUTION
You can create the function and call it in the select statement to index the data into SOLR.
Note : Final results fetched out of functions can be stored in the SOLR.
Example:
CREATE FUNCTION CustomerLevel(p_creditLimit double) RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE lvl varchar(10);
IF p_creditLimit > 50000 THEN
SET lvl = 'PLATINUM';
ELSEIF (p_creditLimit <= 50000 AND p_creditLimit >= 10000) THEN
SET lvl = 'GOLD';
ELSEIF p_creditLimit < 10000 THEN
SET lvl = 'SILVER';
END IF;
RETURN (lvl);
END
Query to used in SOLR for Indexing
SELECT CustomerLevel(123123123) as CustomerLevel from CustomerRating;

How to access a Row Type within an Array Type in DB2 SQL PL

I have a java front end that has a table of data. We need to save this data to the Database via stored procedure. If the passed parameter is a just an array, I am able to access the contents easily. But if the contents of the array is a also a row type, thats the part im having trouble with.
I dont know how to access the contents of the array.
Im using DB2 10.1
CREATE TABLE "TEST"."CHART_ACCT" (
"ACCT_NO" VARCHAR(10) NOT NULL,
"ACCT_DESC" VARCHAR(40) NOT NULL
)
ORGANIZE BY ROW
DATA CAPTURE NONE
IN "USERSPACE1"
COMPRESS YES ADAPTIVE
VALUE COMPRESSION#
CREATE OR REPLACE TYPE TEST.ACCT AS ROW ANCHOR ROW OF TEST.CHART_ACCT#
CREATE OR REPLACE TYPE TEST.ACCT_ARR AS TEST.ACCT ARRAY[]#
CREATE OR REPLACE PROCEDURE TEST.TEST_ARRAY (IN P_ACCT_ARR TEST.ACCT_ARR)
P1: BEGIN
-- #######################################################################
-- #
-- #######################################################################
DECLARE i INTEGER;
SET i = 1;
WHILE i < 10 DO
CALL DBMS_OUTPUT.PUT_LINE(P_GLACCT_ARR[i]);
set i = i + 1;
END WHILE;
END P1#
You need to declare a temporary variable of the row type and assign array elements to it in a loop:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
DECLARE i INTEGER;
DECLARE v_acct acct;
SET i = 1;
WHILE i < CARDINALITY(p_acct_arr) DO
SET v_acct = p_acct_arr[i];
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || v_acct.acct_no);
set i = i + 1;
END WHILE;
END P1#
However, a more concise way to do that is to use the collection-derived table reference:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
FOR r AS (SELECT * FROM UNNEST(p_acct_arr) t ) DO
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || r.acct_no);
END FOR;
END P1#

Resources