I have problem when creating header detail transaction in store procedure. Assume 1 header contain 3 details transaction. If I want to get invoice I must join some table for getting the formula.
USE [M_TENANT]
GO
/****** Object: StoredProcedure [dbo].[generate_billingv2] Script Date: 07/02/2020 09:32:42 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[generate_billingv2]
AS
--exec generate_billingv2
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE #genbill_nochar INT
,#OPT_UTILITY_NOCHAR NVARCHAR(50)
,#NAME_CHAR VARCHAR(80)
,#opt_utility_detail NVARCHAR(50)
,#MD_BILLING_ID_INT INT
,#BILLING_ID_UTILITY INT
,#OPT_UTILITY_AMT NUMERIC
,#BILLING_ID_FORMULA INT
,#FORMULA_PRICE NUMERIC
,#FORMULA_VA NUMERIC
,#FORMULA_NAME VARCHAR(50)
,#MD_FORMULA_PERCENTAGE DECIMAL(18, 3)
,#bill_TYPE INT
,#BASE_INVOICE_AMT NUMERIC
,#OPT_UTILITY_USED NUMERIC
,#ABODEMEN NUMERIC
,#UNIT_LB DECIMAL(18, 3)
,#TAX_UTILITY NUMERIC(18, 3)
,#TOTAL_UTILITY NUMERIC(18, 3)
,#OPT_GENBILL_NOCHAR VARCHAR(50)
,#NOUNIT_CHAR CHAR(20)
,#OPT_GENBILL_STATUS_INT INT
,#OPT_GENBILL_TRX_DATE DATE
,#OPT_UTILITY_TRX_DATE DATE
,#OPT_TRANS_ID_INT INT
,#OPT_GENERATE_BY VARCHAR(50)
,#MD_FORMULA_PRICE NUMERIC
,#USAGE DECIMAL(18, 2)
,#OPT_FLOOR CHAR(10)
,#MD_FORMULA_NAME VARCHAR(50)
,#OPT_START NUMERIC
,#OPT_BILL_END NUMERIC
,#OPT_START_DATE DATE
,#OPT_END_DATE DATE
,#FORMULA_PERCENTAGE DECIMAL(18, 2)
SET #BASE_INVOICE_AMT = 0
SET #TAX_UTILITY = 0
SET #TOTAL_UTILITY = 0
SET #OPT_GENBILL_STATUS_INT = 0
SET #OPT_GENBILL_TRX_DATE = GETDATE()
SET #OPT_GENERATE_BY = 'AUTO'
DECLARE bill_header CURSOR
FOR
SELECT a.OPT_UTILITY_NOCHAR
,a.NOUNIT_CHAR
,b.UNIT_LB
,b.NAME_CHAR
,b.OPT_FLOOR
,a.OPT_TRANS_ID_INT
,a.OPT_UTILITY_TRX_DATE
,0 AS BASE_INVOICE
,0 AS TAX_UTILITY
,0 AS TOTAL_ULTILITY
FROM OPT_UTILITY a
INNER JOIN OPT_TRANS b ON a.OPT_TRANS_ID_INT = b.OPT_TRANS_ID_INT
WHERE a.OPT_GENBILL_STATUS_INT = 0
OPEN bill_header
FETCH NEXT
FROM bill_header
INTO #OPT_UTILITY_NOCHAR
,#NOUNIT_CHAR
,#UNIT_LB
,#NAME_CHAR
,#OPT_FLOOR
,#OPT_TRANS_ID_INT
,#OPT_UTILITY_TRX_DATE
,#BASE_INVOICE_AMT
,#TAX_UTILITY
,#TOTAL_UTILITY
WHILE ##FETCH_STATUS = 0
BEGIN
--HEADER TRANSACTION
--PRINT 'ini header'+'-'+ #OPT_UTILITY_NOCHAR
SET #OPT_GENBILL_NOCHAR = convert(VARCHAR, (
SELECT 'KALINV' + convert(VARCHAR(4), YEAR(GETDATE())) + REPLICATE('0', 5 - LEN(RTRIM(invoiced_count))) + RTRIM(invoiced_count)
FROM counter_table
));
INSERT INTO OPT_GENBILL (
OPT_GENBILL_NOCHAR
,OPT_UTILITY_NOCHAR
,NOUNIT_CHAR
,NAME_CHAR
,LB
,BASE_UTILITY
,TAX_UTILITY
,TOTAL_UTILITY
,OPT_GENBILL_STATUS_INT
,OPT_GENBILL_TRX_DATE
,OPT_UTILITY_TRX_DATE
,OPT_TRANS_ID_INT
,OPT_GENERATE_BY
)
VALUES (
#OPT_GENBILL_NOCHAR
,#OPT_UTILITY_NOCHAR
,#NOUNIT_CHAR
,#NAME_CHAR
,#UNIT_LB
,#BASE_INVOICE_AMT
,#TAX_UTILITY
,#TOTAL_UTILITY
,#OPT_GENBILL_STATUS_INT
,#OPT_GENBILL_TRX_DATE
,#OPT_UTILITY_TRX_DATE
,#OPT_TRANS_ID_INT
,#OPT_GENERATE_BY
)
DECLARE bill_detail CURSOR
FOR
SELECT C.MD_BILLING_ID_INT AS BILL_TYPE
,a.OPT_UTILITY_NOCHAR
,a.MD_BILLING_ID_INT
,b.MD_FORMULA_PRICE
,b.MD_FORMULA_NAME
,b.MD_FORMULA_PERCENTAGE
,b.MD_FORMULA_PJU_ABD AS ABODEMEN
,b.MD_FORMULA_VA AS FORMULA_VA
,a.OPT_BILL_END - a.OPT_UTILITY_AMT AS OPT_START
,a.OPT_BILL_END
,a.OPT_UTILITY_AMT AS USAGE
,a.OPT_START_DATE
,a.OPT_END_DATE
FROM OPT_UTILITY_DETAIL a
INNER JOIN MD_FORMULA b ON a.MD_BILLING_ID_INT = b.MD_FORMULA_ID_INT
INNER JOIN MD_BILLING_TYPE c ON b.MD_BILLING_ID_INT = c.MD_BILLING_ID_INT
WHERE a.OPT_UTILITY_NOCHAR = #OPT_UTILITY_NOCHAR
OPEN bill_detail
FETCH NEXT
FROM bill_detail
INTO #BILL_TYPE
,#OPT_UTILITY_NOCHAR
,#MD_BILLING_ID_INT
,#MD_FORMULA_PRICE
,#MD_FORMULA_NAME
,#MD_FORMULA_PERCENTAGE
,#ABODEMEN
,#FORMULA_VA
,#OPT_START
,#OPT_BILL_END
,#USAGE
,#OPT_START_DATE
,#OPT_END_DATE
--IF exists(select TOP 1* from OPT_GENBILL where OPT_UTILITY_NOCHAR=#OPT_UTILITY_NOCHAR)
--BEGIN
-- ROLLBACK TRANSACTION
-- DEALLOCATE bill_detail
-- RAISERROR('invoice sudah pernah generate ',16,-1,#OPT_UTILITY_NOCHAR)
-- RETURN
--END
IF ##FETCH_STATUS <> 0
PRINT ' <<None>>'
WHILE ##FETCH_STATUS = 0
BEGIN
--SET #BASE_INVOICE_AMT = CASE WHEN #BILL_TYPE=3 AND #USAGE<=40 THEN
-- ((#ABODEMEN*(#FORMULA_VA/1000)*#FORMULA_PRICE)+ ((#ABODEMEN*(#FORMULA_VA/1000)*#FORMULA_PRICE)*#FORMULA_PERCENTAGE))
-- when #bill_TYPE=3 and #USAGE>40 then
-- ((#USAGE*(#FORMULA_VA/1000)*#FORMULA_PRICE)+ ((#USAGE*(#FORMULA_VA/1000)*#FORMULA_PRICE)*#FORMULA_PERCENTAGE))
-- when #bill_TYPE=2 then ((#USAGE*#FORMULA_PRICE)+#ABODEMEN)
-- when #bill_TYPE=1 then #UNIT_LB*#FORMULA_PRICE
-- else 0 end
--print #OPT_UTILITY_NOCHAR
-- print #BILL_TYPE
-- print #USAGE
-- print #ABODEMEN
-- print #FORMULA_PRICE
-- print #FORMULA_VA
-- print #FORMULA_PERCENTAGE
INSERT INTO OPT_GENBILL_DETAIL (
OPT_UTILITY_NOCHAR
,NOUNIT_CHAR
,OPT_START_DATE
,OPT_END_DATE
,OPT_BILL_START
,OPT_BILL_END
,OPT_UTILITY_AMT
,OPT_GENBILL_NOCHAR
)
SELECT #OPT_UTILITY_NOCHAR
,#NOUNIT_CHAR
,OPT_START_DATE
,OPT_END_DATE
,OPT_BILL_END - OPT_UTILITY_AMT
,OPT_BILL_END
,CASE
WHEN #BILL_TYPE = 3
AND #USAGE <= 40
THEN ((#ABODEMEN * (#FORMULA_VA / 1000) * #FORMULA_PRICE) + ((#ABODEMEN * (#FORMULA_VA / 1000) * #FORMULA_PRICE) * #FORMULA_PERCENTAGE))
WHEN #bill_TYPE = 3
AND #USAGE > 40
THEN ((#USAGE * (#FORMULA_VA / 1000) * #FORMULA_PRICE) + ((#USAGE * (#FORMULA_VA / 1000) * #FORMULA_PRICE) * #FORMULA_PERCENTAGE))
WHEN #bill_TYPE = 2
THEN ((#USAGE * #FORMULA_PRICE) + #ABODEMEN)
ELSE 0
END
,#OPT_GENBILL_NOCHAR
FROM OPT_UTILITY_DETAIL
WHERE OPT_UTILITY_NOCHAR = #OPT_UTILITY_NOCHAR
FETCH NEXT
FROM bill_detail
INTO #BILL_TYPE
,#OPT_UTILITY_NOCHAR
,#MD_BILLING_ID_INT
,#MD_FORMULA_PRICE
,#MD_FORMULA_NAME
,#MD_FORMULA_PERCENTAGE
,#ABODEMEN
,#FORMULA_VA
,#OPT_START
,#OPT_BILL_END
,#USAGE
,#OPT_START_DATE
,#OPT_END_DATE
END
CLOSE bill_detail
DEALLOCATE bill_detail
UPDATE counter_table
SET invoiced_count = invoiced_count + 1
UPDATE OPT_UTILITY
SET OPT_GENBILL_STATUS_INT = 1
WHERE OPT_UTILITY_NOCHAR = #OPT_UTILITY_NOCHAR
-- Get the next vendor.
FETCH NEXT
FROM bill_header
INTO #OPT_UTILITY_NOCHAR
,#NOUNIT_CHAR
,#UNIT_LB
,#NAME_CHAR
,#OPT_FLOOR
,#OPT_TRANS_ID_INT
,#OPT_UTILITY_TRX_DATE
,#BASE_INVOICE_AMT
,#TAX_UTILITY
,#TOTAL_UTILITY
END
CLOSE bill_header;
DEALLOCATE bill_header;
COMMIT TRANSACTION
RETURN
But the result 3 detail generating 9 details rows.
Related
I have an SP which brings a table with some fields and subtracts the results to another table, I tried to do this as a function but as you know you can not use DML sentences in a function so I created this SP:
CREATE OR ALTER PROCEDURE SP_Integraciones_AsignarLotesLineas
#Cantidad numeric, #producto nvarchar(max), #bodega nvarchar(max)
AS
BEGIN
BEGIN TRY
BEGIN TRAN
DECLARE #temp as table(idLoteT nvarchar(max), CantidadT numeric, FechaT date)
DECLARE #loteAc nvarchar(Max), #CantidadAc numeric, #restante numeric , #Cont numeric, #fechaAc date, #resultado nvarchar(max)
SET #Cont = #Cantidad
DECLARE CursoIns CURSOR SCROLL
FOR SELECT IdLote, CONVERT(NUMERIC,cantidad), Fecha
FROM tblintegraciones_lotes
WHERE idproducto = #producto
AND Bodega = #bodega
AND cantidad > '0.0'
ORDER BY fecha ASC
OPEN CursoIns
FETCH CursoIns INTO #loteAc, #CantidadAc, #fechaAc
WHILE( #Cont > 0 AND ##FETCH_STATUS = 0 )
BEGIN
IF( #CantidadAc >= #Cont )
BEGIN
SET #restante = #CantidadAc- #Cont
INSERT INTO #temp(
idLoteT, CantidadT, FechaT
)VALUES(
#loteAc, #Cont, #fechaAc
)
UPDATE tblintegraciones_lotes SET Cantidad = #restante WHERE idProducto = #producto AND IdLote = #loteAc
SET #Cont = #cont - #CantidadAc
END
ELSE
BEGIN
SET #Cont = #Cont - #CantidadAc
SET #restante = #Cont - #CantidadAc
INSERT INTO #temp(
idLoteT, CantidadT, FechaT
)VALUES(
#loteAc, #CantidadAc, #fechaAc
)
UPDATE tblintegraciones_lotes SET Cantidad = 0 WHERE idProducto = #producto AND IdLote = #loteAc
END
FETCH CursoIns INTO #loteAc, #CantidadAc, #fechaAc
END
CLOSE CursoIns;
DEALLOCATE CursoIns;
SELECT * FROM #temp
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK
DECLARE #DescripcionError AS nvarchar(max)
SET #DescripcionError = ERROR_MESSAGE()
RAISERROR (#DescripcionError, 18, 1, 'Inventario - lotes - Integraciones', 5)
END CATCH
END
GO
but the problem is that I must run this in a select since I need that query parcing to JSON, so there should be 2 solutions:
Execute this SP in a select sentence
Create some function that calls the SP.
Can you help me how can I execute this SP in a function or find the best soluction?
Here the Query that I need execute this:
(SELECT CASE
WHEN MFAC.codigo IN ('ME-14009',
'ME-14010',
'ME-14011') THEN 'IMP-BOLSAP'
ELSE MFAC.codigo
END AS ItemCode,
REPLACE(MFAC.cantidad, ',', '.') AS Quantity,
CASE WHEN MFAC.codigo LIKE '%PV%' THEN MFAC.valor ELSE null END as Price,
REPLACE(MFAC.descuento, ',', '.') AS DiscountPercent,
CASE
WHEN MFAC.codbodega = 'PV-PER' THEN 'PV-DQU'
ELSE MFAC.codbodega
END AS WarehouseCode,
#OcrCode3 AS CostingCode3,
#OcrCode3 AS COGSCostingCode3
FOR JSON PATH
) DocumentLines
I am trying to insert into an Employee table and I want the if statements to insert into the Salary, NetSalary, and Deduction columns if the Employee will earn a certain amount based on the hourly rate.
If statements are meant to insert data into the relevant column when the amount falls into a particular bracket
ALTER PROCEDURE [dbo].[spSaveEmployee]
(#EmployeePersonName Varchar(20),
#JobTitle int,
#Branch int,
#Department int,
#Manager int,
#HourlyRate MONEY,
#PaymentDate datetime = '2021-10-05 00:00:00.000',
#ErrorMessage Varchar(50) OUTPUT)
AS
BEGIN
DECLARE #DefaultDate DATETIME = GETDATE()
--DECLARE #PAYE INT
--SET #PAYE = 26 / 100
DECLARE #Salary INT
--SET #Salary = #HourlyRate * 180
--DECLARE #PYE INT
--SET #PYE = 1.15
DECLARE #NetSalary MONEY
DECLARE #Deduction DECIMAL (18,2)
DECLARE #NetSalary1 MONEY
DECLARE #NetSalary2 MONEY
DECLARE #NetSalary3 MONEY
--SET #NetSalary = #Salary - #PYE
DECLARE #Deduction1 DECIMAL (18,2)
DECLARE #Deduction2 DECIMAL (18,2)
DECLARE #Deduction3 DECIMAL (18,2)
SET #Deduction1 = (#Salary * 18) / 100
SET #NetSalary1 = #Salary - #Deduction1
SET #Deduction2 = (#Salary * 26) / 100
SET #NetSalary2 = #Salary - #Deduction2
SET #Deduction3 = (#Salary * 31) / 100
SET #NetSalary3 = #Salary - #Deduction3
IF NOT EXISTS (SELECT * FROM EmployeeBook
WHERE EmployeePersonName = #EmployeePersonName)
BEGIN
INSERT INTO EmployeeBook (EmployeePersonName, JobTitle, Branch, Department,
Manager, HourlyRate, PAYE_Tax, Salary,
NetSalary, PaymentDate, Deductions)
VALUES (#EmployeePersonName, #JobTitle, #Branch, #Department,
#Manager, #HourlyRate, 1.15, #Salary,
#NetSalary, #DefaultDate, #Deduction)
SET #ErrorMessage = ''
IF #Salary <= 321000
BEGIN
SELECT #Deduction = #Deduction
SELECT #NetSalary = #NetSalary
END
ELSE IF #Salary >= 321001 AND #Salary <= 445100
BEGIN
SELECT #Deduction = #Deduction2
SELECT #NetSalary = #NetSalary2
END
ELSE IF #Salary >= 445100 AND #Salary <= 584200
BEGIN
SELECT #Deduction = #Deduction3
SELECT #NetSalary = #NetSalary3
END
END
ELSE
BEGIN
SET #EmployeePersonName = ''
SET #JobTitle = 0
SET #Branch = 0
SET #Department = 0
SET #Manager = 0
SET #HourlyRate = 0.00
SET #Salary = 0.00
SET #NetSalary = 0.00
SET #PaymentDate = #DefaultDate
SET #Deduction = 0
SET #ErrorMessage = 'Sorry could not save ' + #EmployeePersonName + ' Employee name already exists'
END
END
GO
The following does what I believe you are trying to accomplish. Issues and comments:
You set your variables after you use them - so they have no effect.
T-SQL is optimised for set-based operations therefore you should attempt to carry out your operations in a set-based manner if possible rather than procedural
Best practice is to use consistent casing for T-SQL
As Larnu points out, error handling is best handled using throw.
Best practice is to always schema prefix your database objects
SPs should always have a return statement
SPs should normally start SET NOCOUNT, XACT_ABORT ON;
Since you can validate the existence of the person straight away, I would and save any further processing time.
What if the salary falls outside the defined brackets? You might not expect it, but you should handle it hence the ELSE in the CASE expression.
I would avoid prefixing your SP's with sp as its too close to the system prefix sp_. In fact why prefix them at all?
When creating brackets like this, one end condition needs to be less than or equal and the other condition greater than (or vice-versa) to avoid a value falling into 2 brackets. Even though the case will short-circuit to the first matching expression, its best from an understanding perspective to have correct and accurate logic.
ALTER PROCEDURE [dbo].[SaveEmployee]
(
#EmployeePersonName VARCHAR(20),
#JobTitle INT,
#Branch INT,
#Department INT,
#Manager INT,
#HourlyRate MONEY,
#PaymentDate DATETIME = '2021-10-05 00:00:00.000',
#ErrorMessage VARCHAR(50) OUTPUT
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
IF EXISTS (SELECT 1 FROM dbo.EmployeeBook WHERE EmployeePersonName = #EmployeePersonName) BEGIN
SET #ErrorMessage = 'Sorry could not save ' + #EmployeePersonName + ' Employee name already exists' END
RETURN;
-- Comment out 2 lines above to uncomment the 2 code line below
-- As suggested by Larnu, this would be more a typical error handling approach
--DECLARE #Error NVARCHAR(2048) = 'Sorry could not save ' + #EmployeePersonName + ' Employee name already exists';
--THROW 51000, #Error, 1;
END;
DECLARE #DefaultDate DATETIME = GETDATE(), #Salary INT = #HourlyRate * 180;
INSERT INTO dbo.EmployeeBook (EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, PAYE_Tax, Salary
, NetSalary, PaymentDate, Deductions)
SELECT EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, 1.15, Salary
, CASE SalaryBracket WHEN 1 THEN Salary - Deduction1
WHEN 2 THEN Salary - Deduction2
WHEN 3 THEN Salary - Deduction3
-- ELSE ??
END
, #DefaultDate
, CASE SalaryBracket WHEN 1 THEN Deduction1
WHEN 2 THEN Deduction2
WHEN 3 THEN Deduction3
-- ELSE ??
END
FROM (
VALUES (#EmployeePersonName, #JobTitle, #Branch, #Department, #Manager, #HourlyRate, 1.15, #Salary
, (#Salary * 18) / 100, (#Salary * 26) / 100, (#Salary * 31) / 100
-- Compute Salary Bracket in one place for reuse
, CASE WHEN #Salary <= 321000 THEN 1
WHEN #Salary > 321001 AND #Salary <= 445100 THEN 2
WHEN #Salary > 445100 AND #Salary <= 584200 THEN 3 END
)
) AS X (EmployeePersonName, JobTitle, Branch, Department, Manager, HourlyRate, PAYE_Tax, Salary, Deduction1, Deduction2, Deduction3, SalaryBracket);
RETURN 0;
END
GO
I have a table below.
Client Name
-----------------------
Mukherjee_ 2697231 Gehrmann _ 298053524
Butt Glen_740708968 Amanda_259055000
Quirk Michael_ 65941412 and Leanne _817498908
Butt Glen_740708968 Amanda_259055000 Tristan 3939393939
Kryger Aaron _ 606506375
Krebs Paul
Haddrill Clare _ 333900499 McRedmond Patrick _557887778
I need to extract the numbers only and the numbers must be separated.
Numeric
----------------
2697231 298053524
740708968 259055000
65941412 817498908
740708968 259055000 3939393939
606506375
333900499 557887778
I have used the function below, however it concatenates all the numbers together.
ALTER FUNCTION [dbo].[UDF_GetNumeric]
(#strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE #intAlpha INT
SET #intAlpha = PATINDEX('%[^0-9]%', #strAlphaNumeric)
BEGIN
WHILE #intAlpha > 0
BEGIN
SET #strAlphaNumeric = STUFF(#strAlphaNumeric, #intAlpha, 1, '' )
SET #intAlpha = PATINDEX('%[^0-9]%', #strAlphaNumeric )
END
END
RETURN ISNULL(#strAlphaNumeric,0)
END
I'm using SQL Server 2012.
Upon looking further into this problem, I came up with -->
-- partition into non-num and numeric strings, collapse non-num into single space, and copy numeric as is
-- complicating: multiple non-num and multiple numeric strings
-- further, allow for starting with EITHER non-num or numeric
-- further, can have no numeric at all, or can have no non-num at all
I put data into table dbo.separatenumber
And created UDF--> Revised Jan 15th--del If/Then/Set #next, add Set #LeftMost
/****** Object: UserDefinedFunction [dbo].[fnSeparateNonNumericCharacters] Script Date: 01/14/2020 21:41:42 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fnSeparateNonNumericCharacters]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[fnSeparateNonNumericCharacters]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE Function [dbo].[fnSeparateNonNumericCharacters](#strText VARCHAR(1000)) RETURNS VARCHAR(1000) AS
BEGIN
Declare #outText as varchar(1000), #LeftMost as char(4), #ndx as int
Set #outText = ''
IF PATINDEX('[0-9]', SUBSTRING(#strText,1,1)) = 1 -- is the 1st char numeric?
Set #LeftMost = 'Nums'
ELSE
Set #LeftMost = 'Text'
;
WHILE LEN(#strText) > 0
BEGIN
IF #LeftMost = 'Text'
BEGIN
Set #ndx = PATINDEX('%[0-9]%', #strText) -- where is the next Numeric
If #ndx = 0 Break -- bail when no more
Set #strText = SUBSTRING(#strText, #ndx, LEN(#strText) - #ndx + 1) -- bypass Text
Set #LeftMost = 'Nums'
END
ELSE -- #LeftMost = 'Nums'
BEGIN
Set #ndx = PATINDEX('%[^0-9]%', #strText) -- where is next Text
If #ndx = 0 Set #ndx = LEN(#strText) + 1 -- use EOL plus one when no more
Set #outText += SUBSTRING(#strText, 1, #ndx - 1) + ' ' -- Grab Numbers plus a space
If #ndx = LEN(#strText) + 1 Break -- bail when no more
Set #strText = SUBSTRING(#strText, #ndx, LEN(#strText) - #ndx + 1 ) -- move past this Num
Set #LeftMost = 'Text'
END
;
END
RETURN #outText -- here it is
END
GO
select
*
, dbo.fnSeparateNonNumericCharacters(clientname) as Numbers
from dbo.separatenumber
Sample output
ClientID ClientName Numbers
11 Mukherjee_ 2697231 Gehrmann _ 298053524 2697231 298053524
22 Butt Glen_740708968 Amanda_259055000 740708968 259055000
33 Quirk Michael_ 65941412 and Leanne _817498908 65941412 817498908
44 Butt Glen_740708968 Amanda_259055000 Tristan 3939393939 740708968 259055000 3939393939
55 Kryger Aaron _ 606506375 606506375
66 Krebs Paul
77 Haddrill Clare _ 333900499 McRedmond Patrick _557887778 333900499 557887778
I have a stored procedure below. In it is a nested loop. Instead of using FETCH_STATUS I want to use something else to mark my cursor as being finished, so that I can do a nested loop. But it's never picking up #Client_ID in the cursor and I don't know why.
ALTER PROCEDURE [dbo].[Import_Agent_Client_Bucket_2010]
AS
BEGIN
-- Loop Through Each Agent, Create a Bucket, Add their Clients to the Bucket
DECLARE Agent_Cursor CURSOR FOR
SELECT TOP 10 Agent_GUID, Agent_ID
FROM realforms_2011.dbo.Agent
DECLARE #Agent_GUID uniqueidentifier
DECLARE #Agent_ID int
OPEN Agent_Cursor;
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
DECLARE #MaxAgentCount int
SELECT #MaxAgentCount = COUNT(Agent_ID)
FROM Agent
DECLARE #AgentCounter int
SET #AgentCounter = 0
WHILE (1 < 2)
BEGIN
PRINT 'Agent Counter:'
PRINT #AgentCounter
SET #AgentCounter = #AgentCounter + 1
-- Create a bucket for each agent
DECLARE #cbPKTable TABLE (cbPK UNIQUEIDENTIFIER, cbID int)
INSERT INTO realforms_2011.dbo.Client_Bucket ([Description] ) OUTPUT inserted.Client_Bucket_GUID, inserted.Client_Bucket_ID INTO #cbPKTable
SELECT ISNULL(a.First_Name, ' ') + ' ' + ISNULL(a.Last_Name, ' ') + '''s Clients'
FROM realforms_2011.dbo.Agent a
WHERE Agent_GUID = #Agent_GUID
DECLARE #Client_Bucket_GUID uniqueidentifier
SELECT #Client_Bucket_GUID = cbPK FROM #cbPKTable
PRINT 'Client Bucket GUID Inserted:'
PRINT #Client_Bucket_GUID
DECLARE #Client_Bucket_ID int
SELECT #Client_Bucket_ID = cbID FROM #cbPKTable
INSERT INTO realforms_2011.dbo.Agent_Client_Bucket (Agent_GUID, Agent_ID, Client_Bucket_GUID, Client_Bucket_ID)
VALUES (#Agent_GUID, #Agent_ID, #Client_Bucket_GUID, #Client_Bucket_ID)
DECLARE #Client_GUID uniqueidentifier
DECLARE #Client_ID int
-- Get clients from the server (2010)
DECLARE Client_Cursor CURSOR FOR
SELECT C.Client_ID
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID
ORDER BY C.Client_ID ASC
DECLARE #MaxClientCreateDate datetime
SELECT #MaxClientCreateDate = MAX(Create_Date)
FROM realforms.dbo.Client C
PRINT 'Max Create Date:'
PRINT #MaxClientCreateDate
DECLARE #ClientCreateDate datetime
SET #ClientCreateDate = CAST('01-01-2000' AS datetime)
OPEN Client_Cursor;
FETCH NEXT FROM Client_Cursor
INTO #Client_ID
-- loop through each 2010 client
WHILE (1 < 2)
BEGIN
DECLARE #myNewPKTable TABLE (myNewPK UNIQUEIDENTIFIER)
BEGIN TRY
PRINT 'Client ID:'
PRINT #Client_ID
PRINT 'Agent ID:'
PRINT #Agent_ID
INSERT INTO realforms_2011.dbo.Client (Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,[Year],IsFavorite) OUTPUT inserted.Client_GUID INTO #myNewPKTable
SELECT c.Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,2010,0
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID AND C.Client_ID = #Client_ID
SELECT #Client_GUID = myNewPK FROM #myNewPKTable
PRINT 'Client GUID Inserted: '
PRINT #Client_GUID
INSERT INTO realforms_2011.dbo.Client_Bucket_Client (Client_Bucket_GUID, Client_GUID, Client_ID, Client_Bucket_ID, [Year])
VALUES (#Client_Bucket_GUID, #Client_GUID, #Client_ID, #Client_Bucket_ID, 2010)
PRINT 'Client Bucket GUID: '
PRINT #Client_Bucket_GUID
PRINT 'Client ID Inserted: '
PRINT #Client_ID
SELECT #ClientCreateDate = CAST(Create_Date as datetime)
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID AND C.Client_ID = #Client_ID
PRINT #ClientCreateDate
END TRY
BEGIN CATCH
PRINT 'Error:'
PRINT ERROR_MESSAGE()
PRINT 'Last Client GUID Inserted: '
PRINT #Client_GUID
PRINT 'Last Client ID: '
PRINT #Client_ID
END CATCH
IF ##ERROR != 0 GOTO ERR_HANDLER
IF (#ClientCreateDate >= #MaxClientCreateDate)
BREAK
FETCH NEXT FROM Client_Cursor
INTO #Client_ID;
END;
CLOSE Client_Cursor;
DEALLOCATE Client_Cursor;
IF (#AgentCounter >= #MaxAgentCount)
BREAK
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
END;
CLOSE Agent_Cursor;
DEALLOCATE Agent_Cursor;
ERR_HANDLER: PRINT 'ERROR'
END
It breaks on #Client_ID
You can nest fetch_status since the last statement of each loop is fetch next.
The stored proc is failing at below location,Thanks, for all your help.
--Insert MSOrg Information
DECLARE #PersonnelNumber int,
#MSOrg varchar(255)
DECLARE csr CURSOR FAST_FORWARD FOR
SELECT PersonnelNumber FROM Person
OPEN csr
FETCH NEXT FROM csr
INTO #PersonnelNumber
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC GetMSOrg #PersonnelNumber, #MSOrg out
INSERT INTO PersonSubject (
PersonnelNumber
,SubjectID
,SubjectValue
,Created
,Updated
)
SELECT #PersonnelNumber
,SubjectID
,#MSOrg
,getDate()
,getDate()
FROM Subject
WHERE DisplayName = 'MS Org'
FETCH NEXT FROM csr
INTO #PersonnelNumber
END
CLOSE csr
DEALLOCATE csr
Below is the stored prc defination GetMSOrg and fails at third condition
CREATE PROCEDURE [dbo].[GetMSOrg]
(
#PersonnelNumber int
,#OrgTerm varchar(200) out
)
AS
DECLARE #MDRTermID int
,#ReportsToPersonnelNbr int
--Check to see if we have reached the top of the chart
SELECT #ReportsToPersonnelNbr = ReportsToPersonnelNbr
FROM ReportsTo
WHERE PersonnelNumber = #PersonnelNumber
IF (#ReportsToPersonnelNbr IS NULL) --Reached the Top of the Org Ladder
BEGIN
SET #OrgTerm = 'Non-standard rollup'
END
ELSE IF (#PersonnelNumber IN (SELECT PersonnelNumber FROM OrgTermMap))
BEGIN
SELECT #OrgTerm = s.Term
FROM OrgTermMap tm
JOIN Taxonomy..StaticHierarchy s ON tm.OrgTermID = s.TermID
WHERE tm.PersonnelNumber = #PersonnelNumber
END
ELSE
BEGIN
SELECT #MDRTermID = tm.OrgTermID
FROM ReportsTo r
JOIN OrgTermMap tm ON r.ReportsToPersonnelNbr = tm.PersonnelNumber
WHERE r.PersonnelNumber = #PersonnelNumber
IF (#MDRTermID IS NULL)
BEGIN
EXEC GetMSOrg #ReportsToPersonnelNbr, #OrgTerm out
END
ELSE
BEGIN
SELECT #OrgTerm = Term
FROM Taxonomy..StaticHierarchy
WHERE VocabID = 118
AND TermID = #MDRTermID
END
END
GO
Each call to EXEC GetMSOrg keeps progressing along the query
SELECT #ReportsToPersonnelNbr = ReportsToPersonnelNbr
FROM ReportsTo
WHERE PersonnelNumber = #PersonnelNumber
And there is an exit clause when PersonnelNumber no longer reports to anyone.
Therefore the only logical conclusion is that you have a cyclical person->reportsto->..->person. This could even be on a single record.
This query will find loops within the reportsto records:
declare #PersonnelNumber int
set #PersonnelNumber = 10
;with CTE as (
select 1 Level,
convert(varchar(max),#PersonnelNumber) Seed,
'>>' + convert(varchar(max),#PersonnelNumber) + '>>' Path
union all
SELECT Level+1,
convert(varchar(max),ReportsToPersonnelNbr),
Path + convert(varchar(max),ReportsToPersonnelNbr) + '>>'
FROM ReportsTo
join CTE on CTE.Seed = ReportsTo.PersonnelNumber
where Level < 40
)
select *
from CTE
where Len(Replace(Path, '>' + convert(varchar(max),Seed) + '>', ''))
= LEN(Path) - Len('>' + convert(varchar(max),Seed) + '>') * 2