I am very new to SQL Server and finally got my code to run, but its very slow. My database is a bit on the big side (1.22mill rows, 3 columns) and I have some while loops, which I know isn't ideal but I couldn't find a way around it.
Any help would be greatly appreciated!!!
declare #b float
declare #c float
declare #dateloopfora datetime
declare #dateloopforc datetime
BEGIN
SET #MYCURSOR = CURSOR FOR
SELECT DISTINCT [STOCKS] FROM [tsxvPrices].[dbo].[3coldata]
OPEN #MYCURSOR
FETCH NEXT FROM #MYCURSOR INTO #STOCK
set #end = '12/30/2012'
WHILE ##FETCH_STATUS = 0
BEGIN
print ('Stockname restart: ' + #stock)
SET #dateloop = '01/01/2012'
WHILE (#dateloop <= #end)
BEGIN
set #datedelta = 0
SET #dateloop = dateadd(day,1,#dateloop)
set #b = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = #dateloop and [stocks] = #stock))
WHILE (#datedelta < 4)
BEGIN
set #datedelta = #datedelta + 1
if (#b is null)
begin
SET #dateloop = dateadd(day,1,#dateloop)
set #b = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = #dateloop and [stocks] = #STOCK))
/*print ('b= ' + cast( #b as varchar(10)) + ' dateadd1=' + cast( #datedelta as varchar(10))) */
end
END
SET #datedelta = 0
set #a = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = dateadd(day,-1,#dateloop) and [stocks] = #stock))
set #c = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = dateadd(day,+96,#dateloop) and [stocks] = #stock))
if #b/#a < 0.8
begin
WHILE (#datedelta < 4)
BEGIN
set #datedelta = #datedelta + 1
if (#a is null)
begin
SET #dateloopfora = dateadd(day,-#datedelta,#dateloop)
set #a = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = #dateloopfora and [stocks] = #STOCK))
/*print ('b= ' + cast( #b as varchar(10)) + ' dateadd1=' + cast( #datedelta as varchar(10))) */
end
if (#c is null)
begin
SET #dateloopforc = dateadd(day,96+#datedelta,#dateloop)
set #c = (SELECT [val] FROM [tsxvPrices].[dbo].[3coldata] WHERE( [dates] = #dateloopforc and [stocks] = #STOCK))
/*print ('b= ' + cast( #b as varchar(10)) + ' dateadd1=' + cast( #datedelta as varchar(10))) */
end
END
/*print ('Stockname: ' + #stock)
print #dateloop
print('daily')
print #b/#a
print ('quarterly')*/
print #c/#b
/*print ('======================')*/
end
END
FETCH NEXT FROM #MYCURSOR INTO #STOCK
END
CLOSE #MYCURSOR
DEALLOCATE #MYCURSOR
I can see one simple problem straight away, you're using a Cursor.
This is probably one of the worst ways to process SQL, it's very slow and it's forcing the SQL engine to be very inefficient.
You're new to SQL so I'll forgo a technical explanation, but please have a look at this other StackOverflow question:
Why is it considered bad practice to use cursors in SQL Server?
I may be able to offer further advice, What version of SQL are you using?
Related
I understand I cant use [USE] statement within a sproc, however I need to query across several databases, this works great stand alone, how can I adapt this query to run across specified databases.
Would I have to Union all and specify each database?
Any Help is greatly appreciated
/* Intalytics section for TB*/
BEGIN
DECLARE #STARTDATE AS DATE = '2022-01-01'
,#ENDDATE AS DATE = '2022-02-28';
SET NOCOUNT ON;
IF OBJECT_ID(N'tempdb.dbo.#TB') IS NOT NULL
DROP TABLE #TB;
DECLARE #intcount INT
DECLARE #DATABASENAME NVARCHAR(25)
SET #intcount = 1
CREATE TABLE #TB (
Current_Database VARCHAR(50)
,Acct VARCHAR(50)
,AcctName NVARCHAR(100)
,[Month] DATETIME
,Oppening_Balance NUMERIC(18, 2)
,[Debit] NUMERIC(18, 2)
,[Credit] NUMERIC(18, 2)
,[Balance] NUMERIC(18, 2)
,[CBalance] NUMERIC(18, 2)
)
CREATE CLUSTERED INDEX ix_tempCIcOMPANY ON #TB (Acct)
WHILE (#intcount <= 23)
BEGIN
IF #intcount = 1
BEGIN
SET #DATABASENAME = 'KSS_INC'
USE [KSS_INC]
END
IF #intcount = 2
BEGIN
SET #DATABASENAME = 'KSS_LTD'
USE [KSS_LTD]
END
IF #intcount = 3
BEGIN
SET #DATABASENAME = 'MPSI_US'
USE [MPSI_US]
END
IF #intcount = 4
BEGIN
SET #DATABASENAME = 'KENTGRPLTD'
USE [KENTGRPLTD]
END
IF #intcount = 5
BEGIN
SET #DATABASENAME = 'KSS_INDIA'
USE [KSS_INDIA]
END
IF #intcount = 6
BEGIN
SET #DATABASENAME = 'KSS_Canada'
USE [KSS_Canada]
END
IF #intcount = 7
BEGIN
SET #DATABASENAME = 'KSS_AUS'
USE [KSS_AUS]
END
IF #intcount = 8
BEGIN
SET #DATABASENAME = 'MPS_INDIA'
USE [MPS_INDIA]
END
IF #intcount = 9
BEGIN
SET #DATABASENAME = 'MPSI_SAF'
USE [MPSI_SAF]
END
IF #intcount = 10
BEGIN
SET #DATABASENAME = 'MPSI_CAN'
USE [MPSI_CAN]
END
IF #intcount = 11
BEGIN
SET #DATABASENAME = 'MPSI_JAP'
USE [MPSI_JAP]
END
IF #intcount = 12
BEGIN
SET #DATABASENAME = 'MPSI_UK'
USE [MPSI_UK]
END
IF #intcount = 13
BEGIN
SET #DATABASENAME = 'MPSI_CHI'
USE [MPSI_CHI]
END
IF #intcount = 14
BEGIN
SET #DATABASENAME = 'KAL_LTD'
USE [KAL_LTD]
END
IF #intcount = 15
BEGIN
SET #DATABASENAME = 'TRADE_AREA_SYSTEMS'
USE [TRADE_AREA_SYSTEMS]
END
IF #intcount = 16
BEGIN
SET #DATABASENAME = 'INTALYTICS'
USE [INTALYTICS]
END
IF #intcount = 17
BEGIN
SET #DATABASENAME = 'KSSL_LTD'
USE [KSSL_LTD]
END
IF #intcount = 18
BEGIN
SET #DATABASENAME = 'MPSI'
USE [MPSI]
END
IF #intcount = 19
BEGIN
SET #DATABASENAME = 'MPSI_INT'
USE [MPSI_INT]
END
IF #intcount = 20
BEGIN
SET #DATABASENAME = 'MPSI_KOR'
USE [MPSI_KOR]
END
IF #intcount = 21
BEGIN
SET #DATABASENAME = 'NEW_SIS_SA'
USE [NEW_SIS_SA]
END
IF #intcount = 22
BEGIN
SET #DATABASENAME = 'MPSICHI_INC'
USE [MPSICHI_INC]
END
IF #intcount = 23 -- to stop loop after last database
BEGIN
BREAK
END
INSERT INTO #TB
SELECT #DATABASENAME
,T1.Account
,T2.AcctName
,CONCAT (
DATENAME(MONTH, T1.RefDate)
,' '
,YEAR(T1.REFDATE)
) AS [Month]
,Isnull((
SELECT SUM(T3.Debit - T3.Credit)
FROM dbo.OJDT T2
INNER JOIN dbo.JDT1 T3 ON T2.TransId = T3.TransId
WHERE DateDiff(dd, T2.RefDate, #StartDate) > 0
AND T3.Account LIKE T1.Account
GROUP BY T3.Account
), 0) 'Opening balance'
,SUM(T1.Debit) 'Debit'
,SUM(T1.Credit) 'Credit'
,SUM(T1.Debit - T1.Credit) AS 'Balance'
,Isnull((
SELECT SUM(T3.Debit - T3.Credit)
FROM dbo.OJDT T2
INNER JOIN dbo.JDT1 T3 ON T2.TransId = T3.TransId
WHERE DateDiff(dd, T2.RefDate, #StartDate) > 0
AND T3.Account LIKE T1.Account
GROUP BY T3.Account
), 0) + SUM(T1.Debit - T1.Credit) AS 'CBalance'
--- CB
FROM OJDT T0
INNER JOIN JDT1 T1 ON T0.TransId = T1.TransId
LEFT JOIN dbo.OACT T2 ON T2.AcctCode = T1.Account /*added to bring through */
WHERE T0.RefDate BETWEEN #StartDate
AND #EndDate
GROUP BY T1.Account
,T2.AcctName
,CONCAT (
DATENAME(MONTH, T1.RefDate)
,' '
,YEAR(T1.REFDATE)
)
,LEFT(DATENAME(MONTH, t1.RefDate), 3) + ' ' + RIGHT('00' + CAST(YEAR(t1.RefDate) AS VARCHAR), 2)
HAVING SUM(T1.Debit - T1.Credit) != 0
SET #intcount = #intcount + 1
END
SELECT *
FROM #TB AS t
END
DECLARE #SQL nvarchar
SET #SQL =''
WHILE (#intcount <= 23)
BEGIN
IF #intcount = 1
BEGIN
SET #DATABASENAME = 'KSS_INC'
USE [KSS_INC]
END
IF #intcount = 2
BEGIN
SET #DATABASENAME = 'KSS_LTD'
USE [KSS_LTD]
END
IF #intcount = 3
BEGIN
SET #DATABASENAME = 'MPSI_US'
USE [MPSI_US]
END
IF #intcount = 4
BEGIN
SET #DATABASENAME = 'KENTGRPLTD'
USE [KENTGRPLTD]
END
IF #intcount = 5
BEGIN
SET #DATABASENAME = 'KSS_INDIA'
USE [KSS_INDIA]
END
IF #intcount = 6
BEGIN
SET #DATABASENAME = 'KSS_Canada'
USE [KSS_Canada]
END
IF #intcount = 7
BEGIN
SET #DATABASENAME = 'KSS_AUS'
USE [KSS_AUS]
END
IF #intcount = 8
BEGIN
SET #DATABASENAME = 'MPS_INDIA'
USE [MPS_INDIA]
END
IF #intcount = 9
BEGIN
SET #DATABASENAME = 'MPSI_SAF'
USE [MPSI_SAF]
END
IF #intcount = 10
BEGIN
SET #DATABASENAME = 'MPSI_CAN'
USE [MPSI_CAN]
END
IF #intcount = 11
BEGIN
SET #DATABASENAME = 'MPSI_JAP'
USE [MPSI_JAP]
END
IF #intcount = 12
BEGIN
SET #DATABASENAME = 'MPSI_UK'
USE [MPSI_UK]
END
IF #intcount = 13
BEGIN
SET #DATABASENAME = 'MPSI_CHI'
USE [MPSI_CHI]
END
IF #intcount = 14
BEGIN
SET #DATABASENAME = 'KAL_LTD'
USE [KAL_LTD]
END
IF #intcount = 15
BEGIN
SET #DATABASENAME = 'TRADE_AREA_SYSTEMS'
USE [TRADE_AREA_SYSTEMS]
END
IF #intcount = 16
BEGIN
SET #DATABASENAME = 'INTALYTICS'
USE [INTALYTICS]
END
IF #intcount = 17
BEGIN
SET #DATABASENAME = 'KSSL_LTD'
USE [KSSL_LTD]
END
IF #intcount = 18
BEGIN
SET #DATABASENAME = 'MPSI'
USE [MPSI]
END
IF #intcount = 19
BEGIN
SET #DATABASENAME = 'MPSI_INT'
USE [MPSI_INT]
END
IF #intcount = 20
BEGIN
SET #DATABASENAME = 'MPSI_KOR'
USE [MPSI_KOR]
END
IF #intcount = 21
BEGIN
SET #DATABASENAME = 'NEW_SIS_SA'
USE [NEW_SIS_SA]
END
IF #intcount = 22
BEGIN
SET #DATABASENAME = 'MPSICHI_INC'
USE [MPSICHI_INC]
END
IF #intcount = 23 -- to stop loop after last database
BEGIN
BREAK
END
SET #SQL =' INSERT INTO #TB
SELECT' + #DATABASENAME +'
,T1.Account
,T2.AcctName
,CONCAT (
DATENAME(MONTH, T1.RefDate)
,'' ''
,YEAR(T1.REFDATE)
) AS [Month]
,Isnull((
SELECT SUM(T3.Debit - T3.Credit)
FROM '+#DATABASENAME+'.dbo.OJDT T2
INNER JOIN '+#DATABASENAME+'.dbo.JDT1 T3 ON T2.TransId = T3.TransId
WHERE DateDiff(dd, T2.RefDate, '+#StartDate+') > 0
AND T3.Account LIKE T1.Account
GROUP BY T3.Account
), 0) ''Opening balance''
,SUM(T1.Debit) ''Debit''
,SUM(T1.Credit) ''Credit''
,SUM(T1.Debit - T1.Credit) AS ''Balance''
,Isnull((
SELECT SUM(T3.Debit - T3.Credit)
FROM '+#DATABASENAME+'.dbo.OJDT T2
INNER JOIN '+#DATABASENAME+'.dbo.JDT1 T3 ON T2.TransId = T3.TransId
WHERE DateDiff(dd, T2.RefDate, '+#StartDate+') > 0
AND T3.Account LIKE T1.Account
GROUP BY T3.Account
), 0) + SUM(T1.Debit - T1.Credit) AS ''CBalance''
--- CB
FROM '+#DATABASENAME+'..OJDT T0
INNER JOIN '+#DATABASENAME+'..JDT1 T1 ON T0.TransId = T1.TransId
LEFT JOIN '+#DATABASENAME+'.dbo.OACT T2 ON T2.AcctCode = T1.Account
WHERE T0.RefDate BETWEEN '+#StartDate+'
AND '+#EndDate+'
GROUP BY T1.Account
,T2.AcctName
,CONCAT (
DATENAME(MONTH, T1.RefDate)
,'' ''
,YEAR(T1.REFDATE)
)
,LEFT(DATENAME(MONTH, t1.RefDate), 3) + '' '' + RIGHT(''00'' + CAST(YEAR(t1.RefDate) AS VARCHAR), 2)
HAVING SUM(T1.Debit - T1.Credit) != 0
SET '+#intcount+' = '+#intcount+' + 1
END
SELECT *
FROM '+#DATABASENAME+'..#TB AS t'
exec(#SQL)
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 have one parent stored procedure and one nested stored procedure. Parent Stored procedure calls the nested stored procedure on loop. Now when there is certain condition matches I have raised the error. When this error is raised I want to stop all the process and return the error.
CREATE Proc [dbo].[Usp_GenSalarySheet](#SalData [HRM].UTDT_SalaryData ReadOnly)
AS
set nocount on
DECLARE #SMT NVARCHAR(MAX)
SET #SMT = 'Create Table ##SalarySheet (StaffID INT,FullName NVARCHAR(1024),PresentDays NVARCHAR(1024),Absent NVARCHAR(1024),Department NVARCHAR(1024),Designation NVARCHAR(1024),'
DECLARE #HopName nvarchar(max)
Declare HOPCursor cursor for select ID from HRM.tbl_HOP
OPEN HOPCursor
FETCH NEXT FROM HOPCursor INTO #HopName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SMT = #SMT + ' [' + #HopName + '] DECIMAL(19,7),'
FETCH NEXT FROM HOPCursor into #HopName
END
SET #SMT = #SMT + '[Total] DECIMAL(19,7))'
CLOSE HOPCursor
DEALLOCATE HOPCursor
print (#smt)
exec (#SMT)
select * into #temp from #SalData
Declare #TopID INT
While (Select Count(*) From #Temp) > 0
Begin
Select Top 1 #TopID = StaffID From #temp
Declare #StaffID INT =(select top 1 StaffID from #temp)
Declare #StaffName NVARCHAR(1024) = (SELECT TOP 1 FullName FROM #temp)
Declare #WorkingDays Int = (SELECT top 1 WorkingDays from #temp)
Declare #Leave INT = (SELECT top 1 [Absent] from #temp)
INSERT INTO ##SalarySheet(StaffID,FullName,[Absent]) values(#StaffID,#StaffName,#Leave)
DECLARE #HOPType INT
DECLARE #Value Decimal(19,7)
DECLARE #CalcVal DECIMAL(19,7) = 0
DECLARE #Formula NVARCHAR(MAX)
DECLARE #Total DECIMAL(19,7)
DECLARE #PayEvery INT
DECLARE #Round Int
Declare HOPList Cursor for SELECT ID,HOPType,Value,Formula,RoundOff,PayEvery FROM HRM.Tbl_HOP order by Schedule
open HOPList
FETCH NEXT FROM HOPList INTO #HopName,#HOPType,#Value,#Formula,#Round,#PayEvery
WHILE ##FETCH_STATUS = 0
BEGIN
if exists(select * from HRM.[Tbl_ContractHOPDetails] where PersonalDetailsID = #StaffID and HOPID = #HopName)
print('select * from HRM.[Tbl_ContractHOPDetails] where PersonalDetailsID = ' + convert(varchar(max), #StaffID) + ' and HOPID =' + convert(varchar(max),#HopName))
begin
if(#HOPType=51)
begin
exec HRM.Usp_GetSalaryValueFromFormula #StaffID,#Formula,#HOPType,#Leave,#WorkingDays,#Value output
set #HOPType= 50
end
if(#HOPType=50)
begin
set #CalcVal = #value
END
IF(#HOPType=38)
BEGIN
SET #CalcVal = #Value - ((#Value/#WorkingDays) * #Leave)
END
if(#PayEvery= 40)
begin
set #CalcVal = ((#CalcVal * #WorkingDays) - (#CalcVal * #Leave))
end
if(#Round = 45)
begin
set #CalcVal = round(#CalcVal,2)
end
else if(#Round = 46)
begin
set #CalcVal = CEILING(#CalcVal)
end
else if(#Round = 47)
begin
set #CalcVal = FLOOR(#CalcVal)
end
set #SMT ='UPDATE ##SalarySheet SET [' + #HopName + '] = ' + cast(#CalcVal as nvarchar(max)) + ' where StaffID = ' + cast(#StaffID as nvarchar(max))
exec (#smt)
end
SET #CalcVal = 0
FETCH NEXT FROM HOPList INTO #HopName,#HOPType,#Value,#Formula,#Round,#PayEvery
END
close HOPList
DEALLOCATE HOPList
set #SMT ='UPDATE ##SalarySheet SET [Total] = ' + cast(#Total as nvarchar(max)) + ' where StaffID = ' + cast(#StaffID as nvarchar(max))
exec (#smt)
Delete #temp Where StaffID = #TopID
end
select * from ##SalarySheet
drop table ##SalarySheet
This is my parent Stored Procudere and nested procedure is as follow:
CREATE proc [HRM].[Usp_GetSalaryValueFromFormula](#StaffID INT,#val nvarchar(max),#HOPType INT,#Leave INT,#WorkingDays INT, #GetResult Decimal(19,7) output)
as
set nocount on
Declare #Formula Varchar(max)
declare #initial INT =0
declare #final INT =0
Declare #DataVal NVARCHAR(MAX) -- set the value from HOP table
declare #FieldVal nvarchar(max)
declare #cnt int = 0
Declare #Complete Int =CHARINDEX ('[',#val,0)
while (#Complete <> 0)
begin
set #initial = CHARINDEX ('[',#val,0)
set #final = CHARINDEX(']',#val,0)
set #FieldVal = SUBSTRING(#val,#initial,(#final-#initial) + 1)
if len(#FieldVal)<>0
begin
select #HOPType = HOPType, #DataVal= ( case when HOPType = 51 then [Formula] else cast([Value] as nvarchar(max)) end) from HRM.Tbl_ContractHOPDetails where PersonalDetailsID = #StaffID and HOPID in(select ID from HRM.tbl_HOP where HOPName = replace(replace(#fieldVal,'[',''),']',''))
if (#DataVal is null or #DataVal ='')
begin
RAISERROR ('Nested HOP is not defined.',11,1)
RETURN
end
print(#DataVal)
if ISNUMERIC(#DataVal)=1
begin
if(#HOPType = 38)
begin
SET #DataVal = cast(#DataVal as decimal(19,7)) - ((cast(#DataVal as decimal(19,7))/#WorkingDays) * #Leave)
end
end
set #val = replace(#val,#fieldVal,#DataVal)
set #fieldVal= ''
set #DataVal = ''
end
set #Complete = CHARINDEX ('[',#val,0)
set #fieldVal =''
set #final =0
set #initial = 0
end
SET #Complete =CHARINDEX ('{',#val,0)
while (#Complete <> 0)
BEGIN
set #initial = CHARINDEX ('{',#val,0)
set #final = CHARINDEX('}',#val,0)
set #FieldVal = SUBSTRING(#val,#initial+1,(#final-#initial)-1)
if len(#FieldVal)<>0
begin
set #DataVal = isnumeric((SELECT 0 FROM [HRM].Tbl_StaffTag where CValue = #FieldVal and StaffID = #StaffID))
set #FieldVal = '{' + #FieldVal + '}'
set #val = replace(#val,#fieldVal,#DataVal)
set #fieldVal= ''
set #DataVal = ''
end
set #Complete = CHARINDEX ('{',#val,0)
set #final =0
set #initial = 0
END
DECLARE #RetrunVal DECIMAL(19,7)
declare #ParmDefinition Nvarchar(512) = '#GetVal decimal(19,7) OUTPUT'
Declare #SMT NVARCHAR(MAX) = ' SET #GetVal = ' + #val
EXECUTE sp_executeSQL #Smt, #ParmDefinition, #GetVal =#RetrunVal OUTPUT
set #GetResult = #RetrunVal
But in current situation it raises error and again from the main procedure it runs next step of loop. But I want to terminate the complete process after this raiserror
Kindly help me
My guess is that RaiseError throws the control back to the caller, which might make the Return statement unreachable. The caller (loop) continues with next iteration.
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 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