我读了一个答案,说你不想在SQL Server中使用WHILE
循环。我不明白这种概括。我对SQL很新,所以我可能还不明白这个解释。我还读到,除非你必须,否则你真的不想使用游标。我发现的搜索结果对于提出的问题太具体了,我无法从中收集有用的技术,所以我把它呈现给你。
我要做的是获取客户端文件中的值并在必要时缩短它们。这里有几件事需要实现。我不能简单地破解提供的字段值。我的公司有标准缩写。我把这些放在表格中,缩写。该表包含LongName
和ShortName
。我不想简单地缩写行中的每个LongName
。只要字段长度太长,我只想应用更新。这就是我需要WHILE
循环的原因。
我的思考过程是:
CREATE FUNCTION [dbo].[ScrubAbbrev]
(@Field nvarchar(25),@Abbrev nvarchar(255))
RETURNS varchar(255)
AS
BEGIN
DECLARE @max int = (select MAX(stepid) from Abbreviations)
DECLARE @StepID int = (select min(stepid) from Abbreviations)
DECLARE @find varchar(150)=(select Longname from Abbreviations where Stepid=@stepid)
DECLARE @replace varchar(150)=(select ShortName from Abbreviations where Stepid=@stepid)
DECLARE @size int = (select max_input_length from FieldDefinitions where FieldName = 'title')
DECLARE @isDone int = (select COUNT(*) from SizeTest where LEN(Title)>(@size))
WHILE @StepID<=@max or @isDone = 0 and LEN(@Abbrev)>(@size) and @Abbrev is not null
BEGIN
RETURN
REPLACE(@Abbrev,@find,@replace)
SET @StepID=@StepID+1
SET @find =(select Longname from Abbreviations where Stepid=@stepid)
SET @replace =(select ShortName from Abbreviations where Stepid=@stepid)
SET @isDone = (select COUNT(*) from SizeTest where LEN(Title)>(@size))
END
END
显然RETURN
应该在最后,但我需要将我的变量重置为下一个@stepID
,@find
和@replace
。
这是我必须使用游标(我从未编写过)的时间吗?
答案 0 :(得分:1)
通常,您不希望在SQL中使用游标或while循环,因为它们一次只处理一行,因此执行效果非常差。 SQL的设计和优化是为了处理(可能非常大的)集数据,而不是单个值。
您可以通过执行以下操作来分解while循环:
UPDATE t
SET t.targetColumn = a.ShortName
FROM targetTable t
INNER JOIN Abbreviations a
ON t.targetColumn = a.LongName
WHERE LEN(t.targetColumn) > @maxLength
这是概括性的,您需要调整它以适合您的特定数据模型,但这是正在发生的事情:
对于“targetTable”中的每一行,将“targetColumn”(您要缩写的内容)的值设置为相关缩写(在Abbreviations.ShortName中找到)iff:当前值具有标准化缩写(内部联接)并且当前值比期望值(where条件)更长。
您需要添加一个整数参数或局部变量@maxLength来指示“太长”的构成。此查询一次处理目标表,更新每个符合条件的行的目标列中的值,而函数一次只能找到单个项(一行和一列的交集)的缩写。
请注意,如果值太长但没有标准缩写,则不会执行任何操作。您现有的代码具有相同的限制,因此我认为这是期望的行为。
我还建议将其作为存储过程而不是函数。 SQL Server上的函数被视为黑盒子,可能严重损害性能,因为优化器通常不太了解它们正在做什么。