编辑说明接近尾声的更新版本
尽管此答案不使用缓存,但它应该最大限度地减少对您的函数的调用次数。使用多个CTEs
来查找 myField1 的不同值,然后使用您的函数在 web 服务中查找不同的值,然后将这些值加入 MyTable。下面的例子可能更清楚:
SQL小提琴
MS SQL Server 2008 架构设置:
CREATE TABLE MyTable
(
ID int PRIMARY KEY IDENTITY,
MyField1 VARCHAR(1)
);
CREATE FUNCTION MyFunction
(
@input As VARCHAR(1)
)
RETURNS VARCHAR(10)
AS
BEGIN
-- This could be a CLR Function
-- Return the result of the function
RETURN CASE @input WHEN 'A' THEN 'aaaaaaaaaa' WHEN 'B' THEN 'bbbbbbbbbb' ELSE 'ccccccccc' END
END;
-- DATA SET UP
DECLARE @i INT = 0
DECLARE @Field VARCHAR(1)
WHILE @i < 1000
BEGIN
SELECT @Field = CASE @i % 3 WHEN 1 THEN 'A' WHEN 2 THEN 'B' ELSE 'C' END
INSERT INTO MyTable (MyField1) VALUES (@Field)
SET @i = @i + 1
END
查询 1:
;WITH DistinctMyField1CTE
AS
(
SELECT DISTINCT MyField1
FROM MyTable
),
LookupValuesCTE
AS
(
SELECT MyField1, dbo.MyFunction(MyField1) As MyOutputField
FROM DistinctMyField1CTE
)
SELECT TOP 20 T1.Id, T1.MyField1, T2.MyOutputField
FROM MyTable T1
INNER JOIN LookupValuesCTE T2
ON T1.MyField1 = T2.MyField1
ORDER BY T1.ID
结果:
| ID | MYFIELD1 | MYOUTPUTFIELD |
---------------------------------
| 1 | C | ccccccccc |
| 2 | A | aaaaaaaaaa |
| 3 | B | bbbbbbbbbb |
| 4 | C | ccccccccc |
| 5 | A | aaaaaaaaaa |
| 6 | B | bbbbbbbbbb |
| 7 | C | ccccccccc |
| 8 | A | aaaaaaaaaa |
| 9 | B | bbbbbbbbbb |
| 10 | C | ccccccccc |
| 11 | A | aaaaaaaaaa |
| 12 | B | bbbbbbbbbb |
| 13 | C | ccccccccc |
| 14 | A | aaaaaaaaaa |
| 15 | B | bbbbbbbbbb |
| 16 | C | ccccccccc |
| 17 | A | aaaaaaaaaa |
| 18 | B | bbbbbbbbbb |
| 19 | C | ccccccccc |
| 20 | A | aaaaaaaaaa |
编辑:
请注意,当我检查 aboce 的 SQL Profiler 跟踪时,我看到对 UDF 的 1000 次调用,换句话说,查询分析器正在生成一个扩展 CTE 并为每一行调用一次 UDF 的计划。
下面使用一个表变量来确保 UDF 只被调用 3 次。我在 SQL Profiler 中对此进行了跟踪,并且效率更高。这使用与上面相同的表和函数。需要附加 SQLFiddle
SQL小提琴
MS SQL Server 2008 架构设置:
CREATE TABLE MyTable
(
ID int PRIMARY KEY IDENTITY,
MyField1 VARCHAR(1)
);
CREATE FUNCTION MyFunction
(
@input As VARCHAR(1)
)
RETURNS VARCHAR(10)
AS
BEGIN
-- This could be a CLR Function
-- Return the result of the function
RETURN CASE @input WHEN 'A' THEN 'aaaaaaaaaa' WHEN 'B' THEN 'bbbbbbbbbb' ELSE 'ccccccccc' END
END;
-- DATA SET UP
DECLARE @i INT = 0
DECLARE @Field VARCHAR(1)
WHILE @i < 1000
BEGIN
SELECT @Field = CASE @i % 3 WHEN 1 THEN 'A' WHEN 2 THEN 'B' ELSE 'C' END
INSERT INTO MyTable (MyField1) VALUES (@Field)
SET @i = @i + 1
END
查询 1:
DECLARE @TempTable TABLE
(
MyField1 VARCHAR(1) PRIMARY KEY,
MyOutputField VARCHAR(10) NULL
)
INSERT INTO @TempTable (MyField1)
SELECT DISTINCT MyField1
FROM MyTable
-- UPDATE Separately otherwise the function gets called
-- for every row in MyTable
UPDATE @TempTable
SET MyOutputField = dbo.MyFunction(MyField1)
SELECT TOP 20 T1.ID, T1.MyField1, T2.MyOutputField
FROM MyTable T1
INNER JOIN @TempTable T2
ON T1.MyField1 = T2.MyField1
结果:
| ID | MYFIELD1 | MYOUTPUTFIELD |
---------------------------------
| 2 | A | aaaaaaaaaa |
| 5 | A | aaaaaaaaaa |
| 8 | A | aaaaaaaaaa |
| 11 | A | aaaaaaaaaa |
| 14 | A | aaaaaaaaaa |
| 17 | A | aaaaaaaaaa |
| 20 | A | aaaaaaaaaa |
| 23 | A | aaaaaaaaaa |
| 26 | A | aaaaaaaaaa |
| 29 | A | aaaaaaaaaa |
| 32 | A | aaaaaaaaaa |
| 35 | A | aaaaaaaaaa |
| 38 | A | aaaaaaaaaa |
| 41 | A | aaaaaaaaaa |
| 44 | A | aaaaaaaaaa |
| 47 | A | aaaaaaaaaa |
| 50 | A | aaaaaaaaaa |
| 53 | A | aaaaaaaaaa |
| 56 | A | aaaaaaaaaa |
| 59 | A | aaaaaaaaaa |