Got integer result when printed return numeric - sql

Not quite understood why I got #res = 1 when print return 0.57? I need to return the numeric results in my UDF function.
DECLARE #text1 VARCHAR(255) = 'some text'
DECLARE #text2 VARCHAR(255) = 'same another text'
DECLARE #res AS NUMERIC
DECLARE #i INT = 0
DECLARE #exist_counter INT = 0
WHILE #i < (LEN(#text1) - 2)
BEGIN
SET #i = #i + 1
IF CHARINDEX(SUBSTRING(#text1, #i, 3), #text2) > 0
BEGIN
SET #exist_counter = #exist_counter + 1
--print #exist_counter
--print SUBSTRING(#text1,#i,3)
END
END
PRINT #i
PRINT #exist_counter
PRINT cast(#exist_counter AS NUMERIC) / cast(nullif(#i, 0) AS NUMERIC)
SET #res = cast(#exist_counter AS NUMERIC) / cast(nullif(#i, 0) AS NUMERIC)
PRINT #res

From this post
Numeric data types that have fixed precision and scale
So you should change scale like.
declare #res as numeric(18, 2)
Why?
As #HABO's comment, "The default precision is 18." and "The default scale is 0" where scale is "The number of decimal digits that are stored to the right of the decimal point."

Related

Generate Next Alphanumeric Code on SQL Server

I need to create a consecutive sequence of varchar(5) (always 5 chars only) code starting from PREVIOUS code.
For example
'00000', '00001', '00002'...'00009', '0000A', '0000B'...'0000Z', '00010','00011'...'ZZZZZ'.
So if I have #PREVIOUS_CODE = '00000', #NEXT_CODE will be '00001'.
If I have #PREVIOUS_CODE = '00009', #NEXT_CODE will be '0000A'
If I have #PREVIOUS_CODE = '0000Z', #NEXT_CODE will be '00010'
So I need something like that
USE [DATABASE]
GO
CREATE PROCEDURE [dbo].[spGetNextCode]
#PREVIOUS_CODE VARCHAR(5)
AS
DECLARE #NEXT_CODE VARCHAR(5)
DO STUFF
...
SELECT #NEXT_CODE AS NEXT_CODE
GO
Any Help?
Just keep an integer counter in the same table and convert it. I'm using the following SQL Server function in one of my applications:
CREATE FUNCTION [dbo].[GetAlphanumericCode]
(
#number BIGINT,
#leadingzeroes INT = 0
)
RETURNS varchar(255)
AS
BEGIN
DECLARE #charPool varchar(36)
SET #charPool = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DECLARE #result varchar(255)
IF #number < 0
RETURN ''
IF #number = 0
SET #result = '0'
ELSE BEGIN
SET #result = ''
WHILE (#number > 0)
BEGIN
SET #result = substring(#charPool, #number % 36 + 1, 1) + #result
SET #number = #number / 36
END
END
IF #leadingzeroes > 0 AND len(#result) < #leadingzeroes
SET #result = right(replicate('0', #leadingzeroes) + #result, #leadingzeroes)
RETURN #result
END
It should be a trivial task to rewrite it as a stored procedure

Insufficient Number of arguments were supplied for Procedure

Quick help I have a Procedure that doesn't let me build in SQL Server: keep saying An insufficient number of arguments were supplied for the procedure or function dbo.GETNEXTBUSINESSDAY. from line 12 to line 15 is where find that error.
My Procedure is dbo.PAYSESTIMATED:
ALTER PROCEDURE [dbo].[PAYSESTIMATED]
(#nLicNum FLOAT, #nYear FLOAT)
AS
BEGIN
DECLARE #dDueDate DATETIME;
DECLARE #nActualTaxes FLOAT;
DECLARE #nPreviousYearTaxes FLOAT;
DECLARE #nQuarterlyTaxesDue FLOAT;
DECLARE #nNetPremium FLOAT;
DECLARE #sQuarterlyDescription VARCHAR(200) = 'PREMIUM TAX QUARTERLY - SURPLUS LINES BROKERS';
DECLARE #sAnnualDescription VARCHAR(200) = 'PREMIUM TAX ANNUAL - SURPLUS LINES BROKERS';
DECLARE #dFirstQuarterDue DATETIME = dbo.GETNEXTBUSINESSDAY(convert(Datetime,Cast(#nYear as varchar(4)) +'/05/31'));
DECLARE #dSecondQuarterDue DATETIME = dbo.GETNEXTBUSINESSDAY(convert(Datetime,Cast(#nYear as varchar(4)) +'/08/31'));
DECLARE #dThirdQuarterDue DATETIME = dbo.GETNEXTBUSINESSDAY(convert(Datetime,Cast(#nYear as varchar(4)) +'/11/30'));
DECLARE #dAnnualDue DATETIME = dbo.GETNEXTBUSINESSDAY(CONVERT(DATETIME, #nYear+ISNULL(1, '') +'/03/1'));
DECLARE #nPreviousAmount FLOAT;
DECLARE #nPaysEstimated FLOAT;
DECLARE #nPaysQuarterly FLOAT;
DECLARE #dToday DATETIME;
SET NOCOUNT ON;
...
My Function for Dbo.GETNEXTBUSSINESSDAY:
ALTER FUNCTION [dbo].[GETNEXTBUSINESSDAY]
( #dDate Datetime, #nDaysAfter Float)
RETURNS datetime AS
BEGIN
DECLARE #dNextDay Datetime = #dDate;
If #nDaysAfter is null or #nDaysAfter < 0 or #dDate is null begin
Return null;
End
If #nDaysAfter = 0 begin
while (dbo.ISHOLIDAY(#dNextDay) = 1) or (RTrim(convert(char,#dNextDay + 'DAY')) in ('SATURDAY','SUNDAY')) Begin
SET #dNextDay = #dNextDay + 1;
End;
RETURN #dNextDay;
End
Else BEGIN
SET #dNextDay = #dNextDay + 1;
declare #i int = 1
while #i <= #nDaysAfter
begin
while (dbo.ISHOLIDAY(#dNextDay) = 1) or (RTrim(convert(char,#dNextDay + 'DAY')) in ('SATURDAY','SUNDAY'))
Begin
SET #dNextDay = #dNextDay + 1;
End
SET #dNextDay = #dNextDay + 1;
set #i = #i+1
End
END
RETURN #dNextDay - 1;
END
Thank You.
Function GETNEXTBUSINESSDAY has two parameters, #dDate Datetime and #nDaysAfter Float
When calling it, provide both parameters, for example
dbo.GETNEXTBUSINESSDAY(convert(Datetime,Cast(#nYear as varchar(4)) +'/05/31'), 0);

SQL Server stored procedure: finding the values of Odd and even

I'm using #subno as Input. And I had to find the odd and even numbers. 16 is not a fix and it can be any other number. My question is how to find the odd and even number of my input?
Lastly, subno includes ( . ) dot at any position. e.g 123456.789123 I need to find the odd and even number of "123456" and the odd and even number of "789123" the dot ( . ) is the separator.
Once you find the odd for the left side, sum them up together. Once you find the even number for left side sum it up as well and then add the total odd to the total even values. That goes the same for the right side eg "789123".
Please help me. this is my 2nd week of trying to find the solution. Once you find all the total values for each side, multiply them together. example "123456" - total value of odd and even * the "789123" total value of odd and even.
It is for the the check digit validation. Validating the subscriber number. after validating through the calculation it should match the calculated reference number to the valid check digit number. It's the business rule. Kind of algorithm
create procedure ProcedureName
(#subno VARCHAR(16), --Input the 16 subscriber number
#result INT OUT,
)
as
begin
IF(LEN(#subno) <> 16)
SET #result = 1 -- INVALID RESULT
ELSE
IF(#subno % 2 = 0)
SET #result = #subno - even numbers
ELSE
SET #result = #subno --odd numbers
end
Please see below my sample work
-- this is the sample
create procedure ProcedureName
(
#subno VARCHAR(20), --Subscriber no
#result INT OUT, --result is invalid for 1, valid for 0
#payamt int
)
as
DECLARE #WA VARCHAR(2)
DECLARE #Weights varchar(9)
DECLARE #I INT
DECLARE #WD INT
DECLARE #WP INT
DECLARE #A INT
DECLARE #B INT
DECLARE #R INT
DECLARE #WR INT
SET #WR = 0
SET #R = 0
SET #A = 0
SET #B = 0
SET #WP = 0
SET #I = 0
BEGIN
IF (LEN(#subNo) = 7) AND (SUBSTRING(#subno,1,1) = '2') OR (SUBSTRING(#subno,1,1) = '9')
BEGIN
SET #result = 0 --VALID
END
ELSE IF(LEN(#subno) = 8) AND (SUBSTRING(#subno,1,1) = '2') OR
(SUBSTRING(#subno,1,1) = '9')
BEGIN
SET #result = 0 --VALID
END
ELSE IF(LEN(#subno) = 9)
BEGIN
SET #WA = SUBSTRING(#subno,1,2)
IF(#WA = '65')
set #result = 1 -- INVALID
else
BEGIN
SET #Weights = '12121212'
SET #WA = SUBSTRING(#subno,9,1)
SET #WD = 0
SET #I = 1
WHILE #I<9
BEGIN
SET #WP = cast(SUBSTRING(#Weights, #I,1)as int) * cast(SUBSTRING(#subno, #I, 1) as int)
IF(#WP > 9)
BEGIN
SET #A = SUBSTRING(CAST(#WP AS VARCHAR),1,1)
SET #B = SUBSTRING(CAST(#WP AS VARCHAR),2,1)
SET #WP = CAST(#A AS INT) + CAST(#B AS INT)
END
SET #WD = #WP + #WD
SET #I = #I + 1
END
SET #R = #WD % 10
IF(#R <> 0)
SET #WR = 10 - #R
ELSE
SET #WR = #R
IF(#WR <> CAST(#WA AS INT))
BEGIN
SET #result = 1 -- INVALID
END
ELSE
BEGIN
SET #result = 0 -- VALID
END
END
END
ELSE IF (LEN(#subno) = 10)
BEGIN
SET #I =1
SET #WD = 0
SET #Weights = '121212121'
SET #WA = SUBSTRING(#subno,10,1)
WHILE(#I < 10)
BEGIN
SET #WP = CAST(SUBSTRING(#Weights, #I, 1)AS INT) * CAST(SUBSTRING(#subno, #I, 1) AS INT)
IF(#WP > 9)
BEGIN
SET #A = SUBSTRING(CAST(#WP AS VARCHAR),1,1)
SET #B = SUBSTRING(CAST(#WP AS VARCHAR),2,1)
SET #WP = CAST(#A AS INT) + CAST(#B AS INT)
END
SET #WD = #WP + #WD
SET #I = #I + 1
END
SET #R = #WD % 10
IF(#R <> 0)
SET #WR = 10 - #R
ELSE
SET #WR = #R
IF (#WR<> #WA)
BEGIN
SET #result = 1 -- INVALID
END
ELSE
BEGIN
SET #result = 0 -- VALID
END
END
ELSE
SET #result = 1 -- INVALID
END
Split the values which u get . Then iterate iver each side and add them. Please see the sample below.
declare #v varchar (16) , #num1 varchar(20) , #num2 varchar(20)
set #v = '1234567.78906656'
select #num1 = substring(#v,0,charindex('.',#v))
select #num2 = substring(#v,charindex('.',#v)+1,len(#v))
--select #num1 = convert(int, substring(#v,0,charindex('.',#v)))
--select #num2 = substring(#v,charindex('.',#v)+1,len(#v))
declare #index int = 1 ,#len INT , #char CHAR
declare #TotalOddL int = 0
declare #TotalEvenL int = 0
DECLARE #FullTotL INT = 0
declare #TotalOddR int = 0
declare #TotalEvenR int = 0
DECLARE #FullTotR INT = 0
DECLARE #TEMP INT
set #len= LEN(#num1)
WHILE #index <= #len
BEGIN
set #char = SUBSTRING(#num1, #index, 1)
SET #TEMP = cast(#char as int)
IF(#TEMP % 2 = 0)
SET #TotalEvenL = #TotalEvenL + #char
else
SET #TotalOddL = #TotalOddL + #char
SET #FullTotL = #TotalEvenL + #TotalOddL
SET #index= #index+ 1
END
Select 'LeftSide total' , #FullTotL
Select 'Left Side odd' , #TotalOddL
Select 'Left Side Even' , #TotalEvenL
SET #index = 1
set #len= LEN(#num2)
WHILE #index <= #len
BEGIN
set #char = SUBSTRING(#num2, #index, 1)
SET #TEMP = cast(#char as int)
IF(#TEMP % 2 = 0)
SET #TotalEvenR= #TotalEvenR + #char
else
SET #TotalOddR = #TotalOddR + #char
SET #FullTotR = #TotalEvenR + #TotalOddR
SET #index= #index+ 1
END
select 'TotalRSide' , #FullTotR
select 'RsideOdd' , #TotalOddR
select 'RSideEven' , #TotalEvenR
select 'Multiplied value' , #FullTotR * #FullTotL
create or replace procedure prc_even_odd(i_number in number, o_result out varchar2)
as
begin
if (mod(i_number,2) = 0) then
o_result := 'EVEN';
else
o_result := 'ODD';
end prc_even;

Function to check the input number of words

Need help to create a function that returns TRUE or FALSE. TRUE - if type 1 or 3 words (like '__hello_', '_hello', '_hello my frend' - spaces should be cut), if the condition is not fulfilled FALSE
CREATE FUNCTION dbo.nazvFac(#f nvarchar(30))
RETURNS bit
AS
BEGIN
DECLARE #l int = 1, #s nvarchar(30), #i int = 0, #b bit
WHILE LTRIM(RTRIM(LEN(#f))) >= #l --error here, but I do not know how to fix it
BEGIN
SET #s = SUBSTRING(#f, #l, 1)
IF #s BETWEEN 'А' AND 'я'
SET #l += 1
ELSE IF #s = ' '
BEGIN
SET #l -= 1
SET #s = SUBSTRING(#f, #l, 1)
SET #s = RTRIM(#s)
SET #l += 2
SET #i += 1
END
ELSE
BREAK
END
IF #i = 0 OR #i = 2
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
GO
WHILE LTRIM(RTRIM(LEN(#f))) >= #l --error here, but I do not know how to fix it
LEN() returns an int, which you are then passing to a string function: RTRIM().
You want to return TRUE only if there are one or three words? This should do it:
CREATE FUNCTION dbo.nazvFac(#f NVARCHAR(30))
RETURNS BIT
AS
BEGIN
DECLARE #l INT, #b BIT
SET #l = LEN(#f) - LEN(REPLACE(#f, ' ', '')) + 1
IF #l == 1 OR #l == 3
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
Also, JC. is right about the len() error.
You should trim the string and then check the length.
CREATE FUNCTION dbo.nazvFac(#f NVARCHAR(30))
RETURNS BIT
AS
BEGIN
DECLARE #l INT = 1, #s NVARCHAR(30), #i INT = 0, #b BIT
WHILE LEN(LTRIM(RTRIM(#f))) >= #l --I think youn need to trim the string and then check length
BEGIN
SET #s = SUBSTRING(#f, #l, 1)
IF #s BETWEEN 'А' AND 'я'
SET #l += 1
ELSE IF #s = ' '
BEGIN
SET #l -= 1
SET #s = SUBSTRING(#f, #l, 1)
SET #s = RTRIM(#s)
SET #l += 2
SET #i += 1
END
ELSE
BREAK
END
IF #i = 0 OR #i = 2
SET #b = 'TRUE'
ELSE
SET #b = 'FALSE'
RETURN #b
END
GO

Convert a number to letters

Given a number, how do you convert that to letters?
You can just translate your existing logic into a t-sql scalar function, like so:
CREATE FUNCTION dbo.fnColumnNameFromIndex(#i int)
RETURNS varchar(3)
AS
BEGIN
DECLARE #dividend int, #letters varchar(3), #modulo int
SET #dividend = #i
SET #letters = ''
WHILE #dividend > 0
BEGIN
SET #modulo = (#dividend - 1) % 26
SET #letters = CHAR(65 + #modulo) + #letters
SET #dividend = CONVERT(int, (#dividend - #modulo) / 26 )
END
RETURN #letters;
END
GO
Call it like this:
SELECT dbo.fnColumnNameFromIndex(2000)
...admittedly not set logic, but I don't see this as a set logic problem.