使用exec推广SQL表查找功能

时间:2017-06-16 10:47:59

标签: sql sql-server sql-server-2014

我有以下SQL函数:

create function [dbo].[LookUpAnonymiseString](@string varchar(500), @tableSize int)
returns varchar(500)
as
begin
       DECLARE @output varchar(500)
       SELECT @output = Value FROM AnonymisationLookup.dbo.Forename WHERE AnonymisationLookup.dbo.Forename.ID = ABS(CHECKSUM(@string)) % @tableSize
       return @output
end
go

我相信这个函数工作正常,它需要一个输入字符串和int表示一个查找表的大小(包含所有可用的字符串)。然后我将输入字符串哈希到索引中以查找表,并在该索引处返回输出字符串的值。

我想概括函数,以便可以在查询中传入和使用表的名称,而不是硬编码的“Forename”表。

我尝试了以下内容,但SQL抱怨并说“只能在函数内执行函数和一些扩展存储过程。”

create function [dbo].[LookUpAnonymiseString](@string varchar(500), @tableName varchar(128), @tableSize int)
returns varchar(500)
as
begin
    declare @output varchar(500)
    declare @sql nvarchar(max) 
    set @sql = N'select @output = Value from AnonymisationLookup.dbo.'+quotename(@tableName)+' where AnonymisationLookup.dbo.'+quotename(@tableName)+'.ID = abs(checksum(@string)) % @tableSize'
    exec sp_executesql @sql, N'@output nvarchar(max) out', @output out
    return @output
end
go

1 个答案:

答案 0 :(得分:1)

您的第一个查询“有点”有效。只有在ID中没有间隙时它才有效 - 并且id很容易产生间隙(甚至是identity列)。所以更安全的方法是:

   DECLARE @output varchar(500);

   SELECT TOP 1 @output = Value
   FROM AnonymisationLookup.dbo.Forename f
   WHERE F.ID >= ABS(CHECKSUM(@string)) % @tableSize
   ORDER BY F.ID;

   return @output;

然后,你传递表的目标不能在一个函数中完成(除非是一个非常复杂,深奥的方式)。因此,你真的不能做你想做的事。您可以在存储过程中使用动态SQL,但不能直接在函数中使用。