我不确定为什么会这样,但是当我运行一些需要较长的多值子值字符串的代码时,会出现随机错误。错误可能是因为我试图在已经存在的临时表中进行插入,尽管我不确定这样做是如何进行的,因为在第一个基本循环的顶部,如果存在的话就将其删除。这样,先前的运行就可以使用它们,如果需要,它们会掉落并再次运行。
现在我几乎可以肯定另一个错误正在失败,然后导致产生误导性的返回消息,但不确定。
这是完整的存储过程。另外,我是一个堆栈开发人员,因此,如果您对此查询有任何好的指针,请随时注意。预先感谢。
可能用于此过程的测试数据字符串:
MITUTOYO〜103-217〜DESC〜^ BROWN&SHARPE〜73〜DESC〜^ MITUTOYO〜103-188〜DESC〜^ MITUTOYO〜103-224A〜DESC〜^ MITUTOYO〜103-225A〜DESC〜^ MITUTOYO〜 103-225A〜DESC〜^ MITUTOYO〜103-189A〜DESC〜^
对于^字符内的每个主要多值,我们将查找制造商和模型,并查看它们是否存在。如果是这样,则返回它;如果不是,则返回它,并在RecommendationsList列中带有新的多值建议列表。这是一个发送的示例,然后找不到匹配项,因此模糊查找也是如此。
制造商ManufacturerPartNumber制造商描述价格项目类型MfrFound模型找到分数建议组
Analyzer Network,0.00,NA,0、1、0,STANDARD,用于HYPRO STANDARD BORE GAGES,31.00,6,^ Harvey Wells ,, FORCE GAUGE 0 35 GMS,93.50,0,^
完整的存储过程:
ALTER PROCEDURE DATA_FuzzyAssetMatchLARGE
/*
PROP: @LISTIN - The entire multi file string sent in from the data file of records.
I=Since the records sent in are a multi value record of sub values meaning (v1.Mfr, v1.Model, v1.Description ^ v2.Mfr, v2.Model, v2.Description ^ ....)
we could in theory have thousands of records to n(3) of string length unknown (n). This being said, we set the value to varchar(max).
varchar(max) unlike varchar wich holds (8000 characters max about 65k bytes), varchar(max) can hold 2 gigs worth of data. That equates to about
1 billion characters since in .NET and others one CHAR is a 2 byte system. This holds mroe then enough.
*/
@LISTIN VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
SET FMTONLY OFF
declare @errorMessage varchar(150) -- ideally would be nice to append to each row so we knew what failed but not break and continue. Not like that at moment
-- ITEMS USED FOR TOP LEVEL RECURSIVE SPLIT LOOP --
declare @pos INT;
declare @len INT;
declare @value varchar(max); -- the value of the first splits (objects) delimed by the ^ character
-- Counter varaibles used to loop and build the one column Suggestion of all matching items
declare @MaxCount integer;
declare @Count integer;
declare @suggestionsStringBuilder varchar(350); --holds the built list of any suggestions.
declare @objectManufacturer varchar(100);
declare @objectModel varchar(150);
declare @objectDescription varchar(150); --the context for this instance to run the params selects for Mfr, Model, Desc
declare @counterIndex int = 0;
declare @objectString varchar(250);
--USED FOR SECOND LEVEL RECURSIVE SPLIT LOOP
declare @objectPosVal INT;
declare @objectLenVal INT;
declare @objectSubstring varchar(250); -- the value used for the secondary split (each object properties such as the actual Mfr, Model, Description, so on....)
--cursor declerations
DECLARE @suggestionsListCursor CURSOR;
DECLARE @CURSOR_Mfr varchar(150);
DECLARE @CURSOR_Model varchar(150);
DECLARE @CURSOR_Desc varchar(150);
DECLARE @CURSOR_Type varchar(20);
DECLARE @CURSOR_Price MONEY;
DECLARE @CURSOR_Score int;
--TEMP TABLE TO STORE FUZZY PREDFINED TABLES IN
IF OBJECT_ID('BASE') IS NOT NULL DROP TABLE BASE
--CREATE THE TEMPTABLE TO WORK WITH
CREATE TABLE BASE
(
Manufacturer varchar(150) null,
ManufacturerPartNumber Varchar(100) null,
ManufacturerDescription varchar(150) null,
Score int ,
Price money,
ItemType varchar(20),
ModelFound bit not null,
MfrFound bit not null,
SuggestionGroup varchar(MAX) null
)
--THIS IS THE LOOP TO PREPARE THE DELIM STRING AND DO A FUZZY MATH OR STRAIGHT MATCH ON EACH OBJECT ROW
set @pos = 0;
set @len = 0;
while charindex('^', @LISTIN, @pos+1)>0
begin
if object_id('tempdb..#TEMPPMFR') is not null drop table #TEMPPMFR
if object_id('tmpdb..#TEMPPMFRMODEL') is not null drop table #TEMPPMFRMODEL
-- stop if there was an error --
if(@errorMessage is not null and @errorMessage != '')
break;
set @suggestionsStringBuilder = '';
set @len = charindex('^', @LISTIN, @pos+1) - @pos;
set @VALUE = substring(@LISTIN,@POS,@LEN-1);
set @objectLenVal = 0;
set @objectPosVal = 0;
set @counterIndex = 0;
set @suggestionsStringBuilder = ''
set @objectManufacturer = ''
set @objectModel = ''
set @objectDescription = ''
--THE LIST COMING IN IS A MULTI-DEMENSIONAL ARRAY OR MULTI-VALUE. IT IS A GROUP OF ENTITYIES, THEN EACH
--ENTITYT IS A GROUP OF PROPERTIES. OUR OUTTER LOOP WE SPLIT ON ENTITITIES.
-- EXAMPLE: @F, @M, @D = Manufacturer, odel, Description
while charindex('~', @value, @objectPosVal+1)>0
begin
set @objectLenVal = charindex('~', @value, @objectPosVal+1) - @objectPosVal
set @objectSubstring = substring(@value, @objectPosVal, @objectLenVal)
if(@counterIndex=0)
set @objectManufacturer = LTRIM(RTRIM(@objectSubstring))
else if(@counterIndex=1)
set @objectModel = LTRIM(RTRIM(@objectSubstring))
else
begin
set @objectDescription = LTRIM(RTRIM(@objectSubstring))
break
end
set @objectPosVal = charindex('~', @value, @objectPosVal+@objectLenVal) +1
end
-- ****
-- **** WE HAVE THE MANUFACTURER AND THE MODEL SO JUST RETURN THE DATA
-- ****
if((select top 1 1 FROM Products_OurProducts_Products where Manufacturer = @objectManufacturer and ManufacturerPartNumber = @objectModel) > 0)
begin try
insert into BASE (
Manufacturer
,ManufacturerPartNumber
,ManufacturerDescription
,Price,ItemType
,MfrFound
,ModelFound
,Score
,SuggestionGroup
)
select
POP.Manufacturer
,POP.ManufacturerPartNumber as Model
,POP.Description
,CONVERT(money,POP.Price) as Price
,POP.ItemType
,CAST('1' as bit) as MfrFound
,CAST('1' as bit) as ModelFound
,CAST('-1' as int) as Score
,'' as SuggestionGroup
from
Products_OurProducts_Products as POP
where
POP.Manufacturer = @objectManufacturer
and
POP.ManufacturerPartNumber = @objectManufacturer
end try
begin catch
SET @errorMessage = (
select
'Number: ' + CAST(ERROR_NUMBER() as varchar(15)) + ' Message:' + ERROR_MESSAGE() AS ErrorMessage
);
end catch
else
-- ****
-- **** WE EITHER FOUND MANUFACTURER SO FUZZY ON MODEL OR VICE VERSA
-- ****
begin try
if((select top 1 1 from Products_OurProducts_Products where Manufacturer = @objectManufacturer) > 0)
begin
--we have to build these temp tables os dynamic columns exist such as MfrFound, ModelFound
select
PMFR.Manufacturer
,PMFR.ManufacturerPartNumber
,PMFR.Description AS ManufacturerDescription
,convert(money,PMFR.Price) as Price
,PMFR.ItemType
,cast('1' as bit) as MfrFound
,cast('0' as bit) as ModelFound
,'' as SuggestionGroup
into
#TEMPPMFR
from
Products_OurProducts_Products as PMFR
where
PMFR.Manufacturer = @objectManufacturer
set @SuggestionsListCursor = cursor for
select top 5
P.Manufacturer
,P.ManufacturerPartNumber as Model
,P.ManufacturerDescription AS 'Description'
,P.Price
,fms.score as Score
from #TEMPPMFR as P
cross apply (
select
dbo.FuzzyControlMatch(@objectModel, P.ManufacturerPartNumber) AS score
) as fms
where
P.Manufacturer = @objectManufacturer
order by
fms.score
desc
open @SuggestionsListCursor
fetch next from
@SuggestionsListCursor
into
@CURSOR_Mfr
,@CURSOR_Model
,@CURSOR_Desc
,@CURSOR_Price
,@CURSOR_Score
while @@FETCH_STATUS = 0
begin
if @suggestionsStringBuilder!=''
set @suggestionsStringBuilder=@suggestionsStringBuilder + @CURSOR_Mfr + ',' + @CURSOR_Model + ',' + @CURSOR_Desc + ',' + convert(varchar(20),@CURSOR_Price) + ',' + convert(varchar(4),@CURSOR_Score) + ', ^ '
else
set @suggestionsStringBuilder = @CURSOR_Mfr + ',' + @CURSOR_Model + ',' + @CURSOR_Desc + ',' + convert(varchar(20),@CURSOR_Price) + ',' + convert(varchar(4),@CURSOR_Score) + ', ^ '
fetch next from
@SuggestionsListCursor
into
@CURSOR_Mfr
,@CURSOR_Model
,@CURSOR_Desc
,@CURSOR_Price
,@CURSOR_Score
end
--Now we insert the original Mfr, Model, Desc, and the suggestions list we build
insert into BASE values(
@objectManufacturer
,@objectModel
,@objectDescription
,'0'
,'0'
,'NA'
,'1'
,'0'
,@suggestionsStringBuilder
)
close @SuggestionsListCursor
deallocate @SuggestionsListCursor
end
else
--IF HAVE A FUZZY AT MFR, THEN WE NEED TO GRAB BEST CHOICE AND GO DOWN.
--WE COULD HAVE POSIBLY CANDIDATES FOR THIS SO WHEN TO STOP RECURSIVENESS AND SAY ADDING NEW ENTRY?
begin
--AT MOMENT JUST RETURN TOP FOUND MFR THEN SELECT FROM THAT TO SEE RESULT TESTS
--FIRST LETS SEE IF SENT MODEL EXIST AND IF SO, PULL THAT THEN RANK AGAINST MFR FOR IT
if((select top 1 1 from Products_OurProducts_Products where ManufacturerPartNumber = @objectModel) > 0)
begin
select
Manufacturer
,ManufacturerPartNumber
,Description AS ManufacturerDescription
,CONVERT(money,Price) AS Price
,ItemType
,CAST('0' as bit) as MfrFound
,CAST('1' as bit) as ModelFound
,'' as SuggestionGroup
into
#TEMPPMFRMODEL
from
Products_OurProducts_Products
where
ManufacturerPartNumber = @objectModel
set @SuggestionsListCursor = cursor for
select top 5
P.Manufacturer
,P.ManufacturerPartNumber as Model
,P.ManufacturerDescription as 'Description'
,P.Price
,fms.score as Score
from #TEMPPMFRMODEL AS P
CROSS APPLY (
select
dbo.FuzzyControlMatch(@objectManufacturer, P.Manufacturer) AS score
) AS fms
where
P.ManufacturerPartNumber = @objectModel
order by
fms.score
desc
--OPEN CURSOR NOW--
open @SuggestionsListCursor
-- NOW LOOP THE RESULTS AND BUILD DEMLIMETER STRING OF SUGESTIONS FOR MFR--
fetch next from @SuggestionsListCursor into @CURSOR_Mfr, @CURSOR_Model, @CURSOR_Desc, @CURSOR_Price, @CURSOR_Score
while @@FETCH_STATUS = 0
begin
if @suggestionsStringBuilder != ''
set @suggestionsStringBuilder = @suggestionsStringBuilder + @CURSOR_Mfr + ',' + @CURSOR_Model + ',' + @CURSOR_Desc + ',' + convert(varchar(20),@CURSOR_Price) + ',' + convert(varchar(4),@CURSOR_Score) + ', ^ '
else
set @suggestionsStringBuilder = @CURSOR_Mfr + ',' + @CURSOR_Model + ',' + @CURSOR_Desc + ',' + convert(varchar(20),@CURSOR_Price) + ',' + convert(varchar(4),@CURSOR_Score) + ', ^ '
fetch next from @SuggestionsListCursor
into @CURSOR_Mfr, @CURSOR_Model, @CURSOR_Desc, @CURSOR_Price, @CURSOR_Score
end
insert into BASE values(
@objectManufacturer
,@objectModel
,@objectDescription
,'0'
,'0'
,'NA'
,'1'
,'0'
,@suggestionsStringBuilder
)
close @SuggestionsListCursor ;
deallocate @SuggestionsListCursor ;
end
else
insert into BASE values(
@objectManufacturer
,@objectModel
,@objectDescription
,'0'
,'0'
,'NA'
,'0'
, '0'
, ''
)
end
--THEN SEE IF EXIST USING FUZZY FOUND MFR, TO SEEK MODEL NUMBER ETC.
END TRY
BEGIN CATCH
SET @errorMessage = (
select
'Number: ' + CAST(ERROR_NUMBER() as varchar(15)) + ' Message:' + ERROR_MESSAGE() AS ErrorMessage
);
END CATCH
SET @pos = CHARINDEX('^', @LISTIN, @pos+@len) +1
END
if(@errorMessage is not null and @errorMessage != '')
select @errorMessage as 'ErrorInfo'
else
select
Manufacturer
,ManufacturerPartNumber
,ManufacturerDescription
,Price
,ItemType
,MfrFound
,ModelFound
,Score
,SuggestionGroup
from
BASE
--NOW REMOVE THE TEMP TABLE
If(OBJECT_ID('BASE') Is Not Null)
BEGIN
DROP TABLE BASE
END
IF(OBJECT_ID('tempdb..#TEMPPMFR') IS NOT NULL)
BEGIN
DROP TABLE #TEMPPMFR
END
IF(OBJECT_ID('tmpdb..#TEMPPMFRMODEL') IS NOT NULL)
BEGIN
DROP TABLE #TEMPPMFRMODEL
END
END
GO