我有一个包含A,B,C列的表和另一个包含列用户名的表。
在C栏中,我有一个函数getName(A)。
getName(A)大致是
CREATE FUNCTION [dbo].[GetName] (
@name VARCHAR(100)
)
RETURNS VARCHAR(100)
WITH SCHEMABINDING
AS
BEGIN
DECLARE @retval VARCHAR(100);
DECLARE @nextWord VARCHAR(100);
SET @retval = @name
IF EXISTS (Select 1 from someTable where username = SUSER_NAME())
BEGIN
SET @name = Replace(Replace(Replace(RTRIM(LTRIM(@name)),',',' ,'),'(','( '),')',' )')
SET @retval = LEFT(@name, 1);
WHILE CHARINDEX(' ', @name, 1) > 0
BEGIN
SET @name = LTRIM(RIGHT(@name, LEN(@name) - CHARINDEX(' ', @name, 1)));
IF CHARINDEX(' ', @name, 1) > 0
BEGIN
SET @nextWord = LTRIM(LEFT(@name, CHARINDEX(' ', @name, 1) - 1))
END
ELSE
BEGIN
SET @nextWord = @name
END
SET @retval += ' ' + CASE
WHEN @nextWord IN (
'List'
,'Of'
,'Different'
,'Words'
)
THEN @nextWord
WHEN ISNUMERIC(@nextWord) = 1
THEN @nextWord
WHEN ISDATE(@nextWord) = 1
THEN @nextWord
ELSE LEFT(@nextWord, 1)
END
END
END
RETURN @retval;
END
现在,当我尝试在查询中使用C列时,它基本上超时了。试图弄清楚是否有办法让它更快。如果C的计算函数只是引用A,则它运行正常。但当它选择A或选择A中每个单词的第一个字母以及允许列表中的单词时,它会变慢。如果我将此功能设为true,则它会相对较快。我尝试了存在但仍然不快。
非常感谢任何建议。
编辑:我更新了上面的功能。我应该注意,当EXISTS查询返回True时它会快速运行,当它返回false时它运行缓慢。这是我感到困惑的更大困境。
答案 0 :(得分:2)
这是一个非常合理的函数,因为它是创建引用另一个表的计算列的唯一方法。
以下代码更安全:
BEGIN
DECLARE @retval VARCHAR(100);
IF EXISTS (SELECT 1 FROM someTable WHERE username = SUSER_NAME)
BEGIN
SET @retval = LEFT(@name, 1);
END
ELSE SET @retval = @name;
RETURN @retval;
END
isnull()
方法很聪明,但如果表中有多行与where
条件匹配,则原始代码会生成错误。此外,它需要考虑表中的所有值,而不仅仅是第一个。 EXISTS
知道停在第一个匹配的行。
您需要sometable(username)
上的索引。您可以通过创建唯一约束或通过显式创建索引来执行此操作。