Я не уверен, почему это происходит, но когда я запускаю какой-то код, который принимает длинную строку с несколькими значениями, я получаю случайную ошибку. Предполагается, что ошибка заключается в том, что я пытаюсь выполнить вставку во временную таблицу, которая уже существует, хотя я не уверен, насколько это возможно, поскольку внутри вершины первого базового цикла я отбрасываю таблицы, если они существуют. Таким образом, их может использовать предыдущий прогон, при необходимости они сбрасываются и снова проходят.
Теперь я почти уверен, что другая ошибка завершается ошибкой, что приводит к вводящему в заблуждение ответному сообщению, но не уверен.
Вот полная хранимая процедура. Кроме того, я стек разработчика, так что если у вас есть хорошие указатели для этого запроса, пожалуйста, не стесняйтесь делать заметки. Заранее спасибо.
Строка ДАННЫХ для тестирования, которая может возникнуть в этой процедуре:
MITUTOYO ~ 103-217 ~ DESC ~ ^ Браун и Шарп ~ 73 ~ DESC ~ ^ MITUTOYO ~ 103-188 ~ DESC ~ ^ MITUTOYO ~ 103-224A ~ DESC ~ ^ MITUTOYO ~ 103-225A ~ DESC ~ ^ MITUTOYO ~ 103-225A ~ DESC ~ ^ MITUTOYO ~ 103-189A ~ DESC ~ ^
Для каждого из основных значений multi в символе ^ мы ищем производителя и модель и видим, существует ли он. Если это так, верните его, если нет, верните его с новым списком предложений с несколькими значениями в столбце SuggesList. Вот пример одного отправленного элемента, затем совпадений не найдено, так же как и нечеткий поиск.
Производитель ПроизводительPartNumber ПроизводительОписание Цена ItemType MfrНайдено моделиНайдено баллов ПредложениеГруппа
Анализатор сети, 0,00, NA, 0, 1, 0, СТАНДАРТ, ИСПОЛЬЗОВАНИЕ ДЛЯ HYPRO STANDARD BORE
GAGES, 31.00,6, ^ Харви Уэллс, FORCE GAGE 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