I have a SQL code for finding whether two words are anagram or not.
DECLARE #str1 VARCHAR(100), #str2 VARCHAR(100)
SELECT #str1 = 'mmaa', #str2 = 'mama'
IF LEN(#str1) <> LEN(#str2)
BEGIN
SELECT 'NOT EQUAL'
END
ELSE
BEGIN
IF (SELECT COUNT(*) FROM
(
select substring(#str1, number, 1) as data
from master..spt_values as m
where m.type='p' and number <= len(#str1) AND number > 0
UNION
select substring(#str2, number, 1) as data
from master..spt_values as m
where m.type='p' and number <= len(#str2) AND number > 0
)
t)
= LEN(#str1)
SELECT '1 anagram'
ELSE
SELECT '0 not anagram'
END
But for words like mmaa and mama this program returns not anagram. But they are anagrams. How can I solve this problem?
rather crude, but how about:
Declare #S1 varChar(100) = 'mmaa'
Declare #S2 varChar(100) = 'mama'
Declare #c char(1)
Declare #i tinyint
Declare #o1 varChar(100) = ''
Declare #o2 varChar(100) = ''
While DataLength(#s1) > 0 Begin
Set #c = Left(#s1, 1)
Set #s1 = Substring(#s1, 2, len(#s1))
Set #i = 1
While #i <= Len(#o1) And #c > substring(#o1, #i, 1) Set #i += 1
Set #o1 = left(#o1, #i-1) + #c + substring(#o1, #i, len(#o1))
End
While DataLength(#s2) > 0 Begin
Set #c = Left(#s2, 1)
Set #s2 = Substring(#s2, 2, len(#s2))
Set #i = 1
While #i <= Len(#o2) And #c > substring(#o2, #i, 1) Set #i += 1
Set #o2 = left(#o2, #i-1) + #c + substring(#o2, #i, len(#o2))
End
Select case When #o1 = #o2 Then 'Anagram' Else 'Not Anagram' End
or to encapsulate the sort into a function,
Create FUNCTION [dbo].[SortString](#s varChar(8000))
RETURNS varChar(8000)
As
Begin
Declare #c char(1)
Declare #i int
Declare #out varChar(8000) = left(#s, 1)
While DataLength(#s) > 0 Begin
Set #s = Substring(#s, 2, len(#s)-1)
Set #c = Left(#s, 1)
Set #i = 0
While #i < Len(#out) And #c > substring(#out, #i+1, 1) Set #i += 1
Set #out = case when #i < Len(#out)
then stuff(#out, #i+1, 0, #c)
else #out + #c end
End
return #out
End
Please try using CHECKSUM_AGG
DECLARE #str1 VARCHAR(100), #str2 VARCHAR(100)
SELECT #str1 = 'mmaa', #str2 = 'mama'
IF LEN(#str1) <> LEN(#str2)
BEGIN
SELECT 'NOT EQUAL'
END
ELSE
BEGIN
IF(SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM (select substring(#str1, number, 1) as data
from master..spt_values as m
where m.type='p' and number <= len(#str1) AND number > 0)T1)=
(SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM (select substring(#str2, number, 1) as data
from master..spt_values as m
where m.type='p' and number <= len(#str2) AND number > 0)T2)
SELECT '1 anagram'
ELSE
SELECT '0 not anagram'
END
Related
I'm looking at pulling two numeric values from a single text string in SQL (2012 version i believe).
The strings are in the following possible formats:
A1234 B4567
or
A:1234 B:4567
or random variants of
A[Symbol/Space/Nothing][Numberstring1] [Space/Nothing] B[Symbol/Space/Nothing][Numberstring2]
Ideally I'd use a combo of substring and charindex but because the symbols/space/nothing at all are used at random i'm finding it difficult.
My preferred output would be 2 columns, one with the [NumberString1] one with [Numberstring2]
Any ideas folks?
You could give this approach a try, it will give you a list of all the number groups. You could then select from the resulting table.
CREATE FUNCTION [dbo].[ParseOutNumbers](#inputText varchar(1000))
RETURNS #ParsedValues TABLE (ID int IDENTITY(1,1),numVal varchar(1000))
AS
BEGIN
DECLARE #charIndex INT
DECLARE #number varchar(1000)
DECLARE #nextChar varchar(1000)
SELECT #charIndex = 1
SELECT #number = ''
WHILE #charIndex <= LEN(#inputText)
BEGIN
SELECT #nextChar = SUBSTRING(#inputText, #charIndex, 1);
IF ISNUMERIC(#nextChar) = 1
BEGIN
SELECT #number = #number + #nextChar
END
IF (ISNUMERIC(#nextChar) = 0 OR #charIndex = LEN(#inputText))
BEGIN
IF (LEN(#number) > 0)
BEGIN
INSERT #ParsedValues(numVal) VALUES(#number)
SELECT #number = ''
END
END
SELECT #charIndex = #charIndex + 1
END
RETURN
END
GO
select * from [dbo].[ParseOutNumbers]('A/d11222Bdd:22002 C23002')
select * from [dbo].[ParseOutNumbers]('A:11222 B:22002 C:23002')
select * from [dbo].[ParseOutNumbers]('A112442B22502C3002')
Alternate version:
CREATE FUNCTION [dbo].[ParseOutNumbersRev2](#inputText varchar(1000))
RETURNS #ParsedValues TABLE (A varchar(1000), B varchar(1000))
AS
BEGIN
DECLARE #charIndex INT
DECLARE #number varchar(1000)
DECLARE #nextChar varchar(1000)
DECLARE #valueIndex INT
SELECT #charIndex = 1
SELECT #number = ''
SELECT #valueIndex = 0
WHILE #charIndex <= LEN(#inputText)
BEGIN
SELECT #nextChar = SUBSTRING(#inputText, #charIndex, 1);
IF ISNUMERIC(#nextChar) = 1
BEGIN
SELECT #number = #number + #nextChar
END
IF (ISNUMERIC(#nextChar) = 0 OR #charIndex = LEN(#inputText))
BEGIN
IF (LEN(#number) > 0)
BEGIN
IF (#valueIndex = 0)
BEGIN
INSERT #ParsedValues(A, B) VALUES(#number, null)
END
ELSE IF (#valueIndex = 1)
BEGIN
UPDATE #ParsedValues SET B = #number
END
SELECT #number = ''
SELECT #valueIndex = #valueIndex + 1
END
END
SELECT #charIndex = #charIndex + 1
END
RETURN
END
GO
select * from [dbo].[ParseOutNumbersRev2]('A/d11222Bdd:22002 C23002')
select * from [dbo].[ParseOutNumbersRev2]('A:11222 B:56 C:23002')
select * from [dbo].[ParseOutNumbersRev2]('A112442B22502C3002')
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;
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
I want to find a credit card numeric value in a sql string.
for example;
DECLARE #value1 NVARCHAR(MAX) = 'The payment is the place 1234567812345678'
DECLARE #value2 NVARCHAR(MAX) = 'The payment is the place 123456aa7812345678'
DECLARE #value3 NVARCHAR(MAX) = 'The payment1234567812345678is the place'
The result should be :
#value1Result 1234567812345678
#value2Result NULL
#value3Result 1234567812345678
16 digits must be together without space.
How to do this in a sql script or a function?
edit :
if I want to find these 2 credit card value.
#value4 = 'card 1 is : 4034349183539301 and the other one is 3456123485697865'
how should I implement the scripts?
You can use PathIndex as
PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', yourStr)
if the result is 0 then it doesnt containg 16 digits other was it contains.
It can be used withing a Where statement or Select statement based on your needs
You can write as:
SELECT case when Len(LEFT(subsrt, PATINDEX('%[^0-9]%', subsrt + 't') - 1)) = 16
then LEFT(subsrt, PATINDEX('%[^0-9]%', subsrt + 't') - 1)
else ''
end
FROM (
SELECT subsrt = SUBSTRING(string, pos, LEN(string))
FROM (
SELECT string, pos = PATINDEX('%[0-9]%', string)
FROM table1
) d
) t
Demo
DECLARE #value1 NVARCHAR(MAX) = 'card 1 is : 4034349183539301 and the other one is 3456123485697865'
DECLARE #Lenght INT
,#Count INT
,#Candidate CHAR
,#cNum INT
,#result VARCHAR(16)
SELECT #Count = 1
SELECT #cNum = 0
SELECT #result = ''
SELECT #Lenght = LEN(#value1)
WHILE #Count <= #Lenght
BEGIN
SELECT #Candidate = SUBSTRING(#value1, #Count, 1)
IF #Candidate != ' '
AND ISNUMERIC(#Candidate) = 1
BEGIN
SET #cNum = #cNum + 1
SET #result = #result + #Candidate
END
ELSE
BEGIN
SET #cNum = 1
SET #result = ''
END
IF #cNum > 16
BEGIN
SELECT #result 'Credit Number'
END
SET #Count = #Count + 1
END
There you go kind sir.
DECLARE
#value3 NVARCHAR(MAX) = 'The payment1234567812345678is the place',
#MaxCount int,
#Count int,
#Numbers NVARCHAR(100)
SELECT #Count = 1
SELECT #Numbers = ''
SELECT #MaxCount = LEN(#value3)
WHILE #Count <= #MaxCount
BEGIN
IF (UNICODE(SUBSTRING(#value3,#Count,1)) >= 48 AND UNICODE(SUBSTRING(#value3,#Count,1)) <=57)
SELECT #Numbers = #Numbers + SUBSTRING(#value3,#Count,1)
SELECT #Count = #Count + 1
END
PRINT #Numbers
You can make this as a function if you are planning to use it a lot.
I just had to scour the internet for this code yet again so I figured I would put it here so I can find it a little faster the next time and hopefully you found it a little faster too :)
Check this.
The code below can check digit in all GTIN's (EAN8, EAN13, EAN14, UPC/A, UPC/E)
CREATE FUNCTION [dbo].[check_digit]
(
#GTIN VARCHAR(14)
)
RETURNS TINYINT
AS
BEGIN
DECLARE #Index TINYINT,
#Multiplier TINYINT,
#Sum TINYINT,
#checksum TINYINT,
#result TINYINT,
#GTIN_strip VARCHAR(13)
SELECT #GTIN_strip = SUBSTRING(#GTIN,1,LEN(#GTIN)-1);
SELECT #Index = LEN(#GTIN_strip),
#Multiplier = 3,
#Sum = 0
WHILE #Index > 0
SELECT #Sum = #Sum + #Multiplier * CAST(SUBSTRING(#GTIN_strip, #Index, 1) AS TINYINT),
#Multiplier = 4 - #Multiplier,
#Index = #Index - 1
SELECT #checksum = CASE #Sum % 10
WHEN 0 THEN '0'
ELSE CAST(10 - #Sum % 10 AS CHAR(1))
END
IF (SUBSTRING(#GTIN,LEN(#GTIN),1) = #checksum)
RETURN 1; /*true*/
RETURN 0; /*false*/
END
CREATE FUNCTION [dbo].[fn_EAN13CheckDigit] (#Barcode nvarchar(12))
RETURNS nvarchar(13)
AS
BEGIN
DECLARE #SUM int , #COUNTER int, #RETURN varchar(13), #Val1 int, #Val2 int
SET #COUNTER = 1 SET #SUM = 0
WHILE #Counter < 13
BEGIN
SET #VAL1 = SUBSTRING(#Barcode,#counter,1) * 1
SET #VAL2 = SUBSTRING(#Barcode,#counter + 1,1) * 3
SET #SUM = #VAL1 + #SUM
SET #SUM = #VAL2 + #SUM
SET #Counter = #Counter + 2;
END
SET #SUM=(10-(#SUM%10))%10
SET #Return = #BARCODE + CONVERT(varchar,((#SUM)))
RETURN #Return
END
And here's a MySQL implementation as well.
Note it requires a 13 digit UPC/EAN13 as input, so you should LPAD your input as required.
drop function if exists barcodify;
delimiter //
at the last digit.
create function barcodify(upc varchar(15))
returns varchar(15)
sql security invoker
begin
declare i, r, odd, even,result int;
set odd=0;
set even =0;
set i = length(upc);
while i > 0 do
set r = substring(upc, i, 1) ;
if(i % 2 >0) then set odd = odd + r;
else set even = even + r;
end if;
set i = i - 1;
end while;
set result = (3*odd)+even;
if result % 10 =0 then return 0;
else return (10 - (result %10));
end if;
end //
delimiter ;
Here's my implementation of a function in Oracle.
CREATE OR REPLACE FUNCTION GenerateCheckDigit(pUPC IN VARCHAR2) RETURN INT
IS
vCheckDigit INT;
BEGIN
WITH barcodeData AS
(
SELECT pUPC barcode FROM dual
)
SELECT
10-REPLACE(MOD(SUM(SUBSTR(barcode, -LEVEL, 1) * DECODE(MOD(LEVEL-1, 2), 1, 1, 3)),10),0,10) INTO vCheckDigit
FROM barcodeData
CONNECT BY LEVEL <= LENGTH(barcode);
RETURN vCheckDigit;
END;
To calculate the last digit.
https://segovoni.medium.com/sql-server-function-to-calculate-gs1-barcode-check-digit-d55b478ff645
CREATE FUNCTION dbo.udf_GetGS1EAN13CheckDigit
(
#ACode AS VARCHAR(12)
)
RETURNS SMALLINT
AS BEGIN
/*
Author: Sergio Govoni
Notes: Calculate the check-digit of a GS1 EAN13 code
Version: 1.0
*/
DECLARE
#tmpCode AS VARCHAR(12)
,#tmpMulSup AS VARCHAR(8000)
,#tmp AS VARCHAR(8000)
,#i AS INT
,#j AS INT
,#z AS INT
,#SumDEven AS INT
,#SumDOdd AS INT
,#List AS VARCHAR(8000)
,#tmpList AS VARCHAR(8000)
,#CheckSum AS SMALLINT
SET #SumDEven = 0
SET #SumDOdd = 0
SET #List = ''
SET #tmpList = ''
SET #tmp = ''
SET #tmpCode = #ACode
/* 0. List builder */
SET #j = LEN(#tmpCode) + 1
SET #i = 1
WHILE (#i <= LEN(#tmpCode)) BEGIN SET #List = #List + '|' + LTRIM(RTRIM(STR(#j))) + ';' + SUBSTRING(#tmpCode, #i, 1) SET #j = (#j - 1) SET #i = (#i + 1) END /* 1. Add up the digits in even position */ SET #i = 1 SET #tmpList = #List WHILE (CHARINDEX('|', #tmpList) > 0)
BEGIN
SET #j = CHARINDEX('|', #tmpList)
SET #z = CHARINDEX(';', #tmpList)
IF (CAST(SUBSTRING(#tmpList, (#j + 1), (#z - (#j + 1))) AS INTEGER) % 2) = 0
BEGIN
SET #SumDEven = #SumDEven + CAST(SUBSTRING(#tmpList, (#z + 1), 1) AS INTEGER)
END
SET #tmpList = SUBSTRING(#tmpList, (#z + 2), LEN(#tmpList))
END
/* 2. Multiply the result of the previous step (the first step) to 3 (three) */
SET #SumDEven = (#SumDEven * 3)
/* 3. Add up the digits in the odd positions */
SET #i = 1
SET #tmpList = #List
WHILE (CHARINDEX('|', #tmpList) > 0)
BEGIN
SET #j = CHARINDEX('|', #tmpList)
SET #z = CHARINDEX(';', #tmpList)
IF (CAST(SUBSTRING(#tmpList, (#j + 1), (#z - (#j + 1))) AS INTEGER) % 2) <> 0
BEGIN
SET #SumDOdd = #SumDOdd + CAST(SUBSTRING(#tmpList, (#z + 1), 1) AS INTEGER)
END
SET #tmpList = SUBSTRING(#tmpList, (#z + 2), LEN(#tmpList))
END
/* 4. Add up the results obtained in steps two and three */
SET #CheckSum = (#SumDEven + #SumDOdd)
/* 5. Subtract the upper multiple of 10 from the result obtained in step four */
IF ((#CheckSum % 10) = 0)
BEGIN
/* If the result of the four step is a multiple of Ten (10), like
Twenty, Thirty, Forty and so on,
the check-digit will be equal to zero, otherwise the check-digit will be
the result of the fifth step
*/
SET #CheckSum = 0
END
ELSE BEGIN
SET #tmpMulSup = LTRIM(RTRIM(STR(#CheckSum)))
SET #i = 0
WHILE #i <= (LEN(#tmpMulSup) - 1)
BEGIN
SET #tmp = #tmp + SUBSTRING(#tmpMulSup, #i, 1)
IF (#i = LEN(#tmpMulSup) - 1)
BEGIN
SET #tmp = LTRIM(RTRIM(STR(CAST(#tmp AS INTEGER) + 1)))
SET #tmp = #tmp + '0'
END
SET #i = (#i + 1)
END
SET #CheckSum = CAST(#tmp AS INTEGER) - #CheckSum
END
RETURN #CheckSum
END;
CREATE FUNCTION sfn_ean_chkdigit(#barcode varchar(20))
RETURNS CHAR(1)
AS
BEGIN
DECLARE #chk_digit int, #chk int
DECLARE #num TABLE (num int)
IF LEN(#barcode) NOT IN (7, 12) RETURN NULL
INSERT INTO #num
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL
SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
SELECT #chk_digit = SUM(CONVERT(int, SUBSTRING(#barcode, LEN(#barcode) - num + 1, 1)) * CASE WHEN num % 2 = 1 THEN 3 ELSE 1 END)
FROM #num
WHERE num <= LEN(#barcode)
SELECT #chk_digit = (10 - (#chk_digit % 10)) % 10
RETURN CHAR(ASCII('0') + #chk_digit)
END
Num unico script
select lpad('123456789012',12,'0') || ( (r+1)*10 - soma )%10
from (select sum(v::int * case when i%2=0 then 3 else 1 end) soma,
round(sum(v::int * case when i%2=0 then 3 else 1 end)/10.0) r
from unnest(string_to_array(lpad('123456789012',12,'0'),null)) with ordinality d(v,i)
) a