我是SQL Server 2008的新手。非常感谢任何帮助。如果我写的存储过程是耗时因素,有人可以帮我写一个更好的方法。
Table Name: tblProduct
Column Names: Product No, S1_CR, S1_CAT1, S1_CAT2, S1_CAT3, S1_CAT4
Eg Column Values: 1234, Prod1#Prod2#Prod3, 10#200#300, 20#34#400, 40#12#12, 50#23#12
我正在尝试填充一个表格(当输入为Prod2时),
1234 Prod2 200 34 12 23
执行以下存储过程时会出现以下错误。
错误:超出了最大存储过程,函数,触发器或视图嵌套级别(限制32)。
存储过程有一个函数(instr),调用该函数来查找字符串中哈希的出现次数,以帮助填充表。
存储过程:
Alter Procedure spPopulate
@Code varchar(10),
@Test int,
@Product varchar(10),
@Year varchar(4)
as
Begin
Declare @Pos int
select @Pos = LEN(SUBSTRING(S1_CR, 0, CHARINDEX(@Code, S1_CR, 0))) - LEN(REPLACE(SUBSTRING(S1_CR, 0, CHARINDEX(@Code, S1_CR, 0)), '#' , '')) from tblProduct where Product =@Product and Year = @Year
select ProductNo, s1_cr, s1_cat1, S1_CAT2, S1_CAT3, S1_CAT4,
case
when @Test >= 1 then right(LEFT(s1_CAT1, dbo.INSTR(S1_CAT1+ '#', '#', 1, @Pos+1)-1), (dbo.INSTR(S1_CAT1+ '#', '#', 1, @Pos+1)-1)- (dbo.INSTR(S1_CAT1+ '#', '#', 1, @Pos)+1)+1) end as CAT1,
case
when @Test >= 2 then right(LEFT(s1_CAT2, dbo.INSTR(S1_CAT2+ '#', '#', 1, @Pos+1)-1), (dbo.INSTR(S1_CAT2+ '#', '#', 1, @Pos+1)-1)- (dbo.INSTR(S1_CAT2+ '#', '#', 1, @Pos)+1)+1) end as CAT2,
case
when @Test >= 3 then right(LEFT(s1_CAT3, dbo.INSTR(S1_CAT3+ '#', '#', 1, @Pos+1)-1), (dbo.INSTR(S1_CAT3+ '#', '#', 1, @Pos+1)-1)- (dbo.INSTR(S1_CAT3+ '#', '#', 1, @Pos)+1)+1) end AS CAT3,
case
when @Test >= 4 then right(LEFT(s1_CAT4, dbo.INSTR(S1_CAT4+ '#', '#', 1, @Pos+1)-1), (dbo.INSTR(S1_CAT4+ '#', '#', 1, @Pos+1)-1)- (dbo.INSTR(S1_CAT4+ '#', '#', 1, @Pos)+1)+1) end AS CAT4
from Product where Product=@Product and Year = @Year ;
End
Execute spPopulate @Code = 'Prod1', @Product= 'ProductName1', @Year = '2010', @Test = 1
请在下面找到instr
的功能 ALTER FUNCTION [dbo].[INSTR] (@str VARCHAR(8000), @substr VARCHAR(255), @start INT, @occurrence INT)
RETURNS INT
AS
BEGIN
DECLARE @found INT = @occurrence,
@pos INT = @start;
WHILE 1=1
BEGIN
-- Find the next occurrence
SET @pos = CHARINDEX(@substr, @str, @pos);
-- Nothing found
IF @pos IS NULL OR @pos = 0
RETURN @pos;
-- The required occurrence found
IF @found = 1
BREAK;
-- Prepare to find another one occurrence
SET @found = @found - 1;
SET @pos = @pos + 1;
END
RETURN @pos;
END
答案 0 :(得分:0)
您收到的错误消息与递归调用有关。
在您的解决方案中,您没有放置“GO'在' END'之间以及程序的测试执行。 可能性是将测试的执行编译到过程代码本身。
答案 1 :(得分:0)
我将假设此练习的目的是将值拆分出列,以便您可以规范化数据。
-- set up our sample datasource
declare @source as table
(
ProductNo int,
S1_CR varchar(100),
S1_CAT1 varchar(100),
S1_CAT2 varchar(100),
S1_CAT3 varchar(100),
S1_CAT4 varchar(100)
)
insert into @source values (1234, 'Prod1#Prod2#Prod3', '10#200#300', '20#34#400', '40#12#12', '50#23#12')
-- set up what will become input parameters to our sp
declare @prodNo int = 1234
declare @code varchar(10) = 'Prod2'
--Note that there are not Columns named Product, Year in the sample data but you refer to it in your Query so I assume they exist
declare @Product varchar(10) -- is your declaration long enough? calling your sp you use 'ProductName1' which wont fit.
declare @year varchar(4) = '2010'
-- this could be a constant if it doesnt change from record to record,
-- or a parameter if it does
declare @delimiter char = '#'
--declare our variables
declare @output table
(
ProductNo int,
S1_CR varchar(100),
S1_CAT1 varchar(100),
S1_CAT2 varchar(100),
S1_CAT3 varchar(100),
S1_CAT4 varchar(100)
)
declare @ProductNo int
declare @S1_CR varchar(100)
declare @S1_CAT1 varchar(100)
declare @S1_CAT2 varchar(100)
declare @S1_CAT3 varchar(100)
declare @S1_CAT4 varchar(100)
--these ones are used during validation
declare @index int = 1
declare @term_count int = 0 -- this counts the number of terms in the column we are looking at
declare @num_terms int = 0 -- this becomes our fixed comparison value
declare @reviewing varchar(100) -- this is the data from the column we are looking at
select
@ProductNo = s.ProductNo,
@S1_CR = s.S1_CR + @delimiter,
@S1_CAT1 = s.S1_CAT1 + @delimiter,
@S1_CAT2 = s.S1_CAT2 + @delimiter,
@S1_CAT3 = s.S1_CAT3 + @delimiter,
@S1_CAT4 = s.S1_CAT4 + @delimiter
from @source s
where s.ProductNo = @prodNo
set @reviewing = @S1_CR
--validate to ensure there are equal number of concatenated terms in each column
--you will probably want to do other validation on inputs etc.
while @index > 0 --and @num_terms > 0
begin
set @index = CHARINDEX(@delimiter, @reviewing, @index +1)
if @index > 0
set @term_count = @term_count + 1
else if @index = 0 and @term_count @num_terms and @reviewing @S1_CR -- num_terms will be zero when reviewing the first column
set @num_terms = 0
else
begin
select
@num_terms = case @reviewing
when @S1_CR then @term_count
else @num_terms
end,
@reviewing = case @reviewing
when @S1_CR then @S1_CAT1
when @S1_CAT1 then @S1_CAT2
when @S1_CAT2 then @S1_CAT3
when @S1_CAT3 then @S1_CAT4
else ''
end
if @reviewing = ''
set @index = 0
else
set @index = 1
set @term_count = 0
end
end
--Split out the terms
while @num_terms > 0
begin
insert into @output values
(
@ProductNo,
left(@S1_CR,CHARINDEX(@delimiter,@S1_CR,1) -1),
left(@S1_CAT1,CHARINDEX(@delimiter,@S1_CAT1,1) -1),
left(@S1_CAT2,CHARINDEX(@delimiter,@S1_CAT2,1) -1),
left(@S1_CAT3,CHARINDEX(@delimiter,@S1_CAT3,1) -1),
left(@S1_CAT4,CHARINDEX(@delimiter,@S1_CAT4,1) -1)
)
set @S1_CR = right(@S1_CR,len(@S1_CR) - CHARINDEX(@delimiter,@S1_CR,1))
set @S1_CAT1 = right(@S1_CAT1,len(@S1_CAT1) - CHARINDEX(@delimiter,@S1_CAT1,1))
set @S1_CAT2 = right(@S1_CAT2,len(@S1_CAT2) - CHARINDEX(@delimiter,@S1_CAT2,1))
set @S1_CAT3 = right(@S1_CAT3,len(@S1_CAT3) - CHARINDEX(@delimiter,@S1_CAT3,1))
set @S1_CAT4 = right(@S1_CAT4,len(@S1_CAT4) - CHARINDEX(@delimiter,@S1_CAT4,1))
set @num_terms = @num_terms - 1
end
select * from @output where S1_CR = @code