我有几个嵌套的插入命令。一些嵌套循环共享冗余代码。我应该将冗余代码作为自己的循环,还是在每个循环中创建相同代码的单独实例?
示例(编辑以供澄清):
--Questions 32<->37
SET @index=0
SET @values = 'at your primary grocery store^at WalMart or Sam''s Club^at any other chain (e.g. Target, K-Mart)^in general'
IF SUBSTRING(@values, LEN(@values), 1) <> '^' SET @values = @values + '^'
WHILE (LEN(@values)<>0)
BEGIN
SET @index=CHARINDEX('^', @values)
SET @result=SUBSTRING(@values, 0, @index)
SET @values=SUBSTRING(@values, LEN(@result)+2, LEN(@values)-LEN(@result)-1)
SET @question = 'How much do you spend <b>'+@result+'</b> per trip compared to this time last year?'
SET @qnum=@qnum+1
INSERT INTO checklist_questions (
checklist_id
,checklist_question_id
,checklist_answer_category_id
,autofail_flag
,checklist_responsible_type_id
,correction_days
,checklist_question_header_id
,question
)
VALUES (
@checklist_id
,@qnum --question #
,40 --answer category id
,0 --autofail flag
,'P' --checklist_responsible_type_id
,27 --correction_days
,4 --correction_days
,@question
)
SET @i=1
WHILE (@i<=6)
BEGIN
INSERT INTO checklist_answers (
checklist_id
,checklist_question_id
,checklist_answer_category_id
,checklist_answer_type_id
,detail_flag
)
VALUES (
@checklist_id
,@qnum --question number
,38 --category
,@i --answer type
,0 --detail flag
)
SET @i=@i+1
END
END
相同的模式反复重复,使用@values和@question的不同值。
答案 0 :(得分:3)
我同意评论者的意见 - 摆脱循环。你有一个强大的,基于集合的语言,你正在编写程序代码。我建议重新评估问题,以形成一个更适合SQL Server的解决方案(这里有一个可以帮助你的社区)。虽然你正在做的事情会起作用(并且可能确实如此),但这将是一个维护问题。
答案 1 :(得分:3)
好的,这应该有效:
**
**
declare @checklist_id INT;
SET @checklist_id = 99 -- ??
declare @index INT, @values VARCHAR(MAX);
SET @index=0
SET @values = 'at your primary grocery store^at WalMart or Sam''s Club^at any other chain (e.g. Target, K-Mart)^in general'
-- make sure all substring are bounded on both sides
IF SUBSTRING(@values, LEN(@values), 1) <> '^' SET @values = @values + '^'
IF LEFT(@values,1) <> '^' SET @values = @values + '^'
;WITH cteNumbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY object_id) as N
FROM master.sys.system_columns --just a convenient source of rows
)
, cteValues AS
(
SELECT SUBSTRING(@values, N+1, CHARINDEX('^', @values, N+1)-1) as value
, ROW_NUMBER() OVER(ORDER BY N) AS qnum
FROM cteNumbers
WHERE N < LEN(@values)
AND SUBSTRING(@values, N, 1) = '^'
)
INSERT INTO checklist_questions (
checklist_id
,checklist_question_id
,checklist_answer_category_id
,autofail_flag
,checklist_responsible_type_id
,correction_days
,checklist_question_header_id
,question
)
SELECT
@checklist_id
,qnum --question #
,40 --answer category id
,0 --autofail flag
,'P' --checklist_responsible_type_id
,27 --correction_days
,4 --correction_days
,'How much do you spend <b>'+ value +'</b> per trip compared to this time last year?'
FROM cteValues;
;WITH cteNumbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY object_id) as N
FROM master.sys.system_columns --just a convenient source of rows
)
, cteValues AS
(
SELECT SUBSTRING(@values, N+1, CHARINDEX('^', @values, N+1)-1) as value
, ROW_NUMBER() OVER(ORDER BY N) AS qnum
FROM cteNumbers
WHERE N < LEN(@values)
AND SUBSTRING(@values, N, 1) = '^'
)
INSERT INTO checklist_answers (
checklist_id
,checklist_question_id
,checklist_answer_category_id
,checklist_answer_type_id
,detail_flag
)
SELECT
@checklist_id
,qnum --question number
,38 --category
, N --answer type
,0 --detail flag
FROM cteValues AS v
CROSS JOIN (SELECT N FROM cteNumbers WHERE N <= 6) AS num;
答案 2 :(得分:1)
我使用以下规则:
答案 3 :(得分:0)
我把所有这些放在一个循环中。因为唯一的区别是,一组东西是从{0}到{4}完成的,另一组是5..9,使用IF语句在它们之间切换,例如:
@foo
答案 4 :(得分:0)
像所有必须使用现有代码库的人一样,我遇到了这样的代码。海报是“做正确的事”TM,因为他们使用循环而不是游标(Yeck!)。
解决需要循环问题的一种方法是查看STUFF和OTHER STUFF占位符中的内容。也许你不需要一个循环,但两个不同的陈述。尝试弄清楚为什么需要循环以及是否可以插入/更新一组数据。
在任何情况下,在你转移到其他东西之后必须处理代码的人会感谢你,如果现在去那个额外的院子。
答案 5 :(得分:0)
我将输入拆分为临时表或表变量,然后在基于select not a values子句的insert语句中使用它。
答案 6 :(得分:-1)
在不知道所有细节的情况下,我建议使用sproc或函数来封装冗余代码。