在 UDF from 子句中使用参数

Posted

技术标签:

【中文标题】在 UDF from 子句中使用参数【英文标题】:Using a parameter in UDF from clause 【发布时间】:2011-06-23 13:46:36 【问题描述】:

我在 SQL Server 2008 中有一个用户定义的函数。这里是:

CREATE FUNCTION [dbo].[GetAddressByEntityNameAndId] 
(
-- Add the parameters for the function here
@entityName varchar (100),
@parentEntityId int
)
RETURNS varchar(300)
AS
BEGIN
-- Declare the return variable here
DECLARE @Address varchar(300)

if(@entityName = 'Staff')
BEGIN

    select @Address = ca.Address + ' ' + ca.City + ' ' + ca.State + ' ' + ca.ZipCode
    from @entityName cc 
    inner join  ContactAddress ca on ca.ParentEntityId = cc.Id 
    inner join EntityName en on en.Id = ca.EntityNameId and en.Name = @entityName 
    inner join GeneralLookup gl on ca.glAddressTypeId = gl.Id and gl.LookupItem = 'Primary' 
    where cc.Id = @parentEntityId

END 
-- Return the result of the function
RETURN @Address

END

但它没有被执行。错误信息是:

Must declare the table variable "@entityName".

任何帮助将不胜感激。

更新:

好的,现在我有另一个问题。这是我的 SP:

ALTER PROCEDURE [dbo].[spGetStaffsAndClients]

AS
BEGIN

declare @Address varchar (100)
declare @Apartment varchar (100)
declare @City varchar (100)
declare @State varchar (10)
declare @Zip varchar (10)
declare @County varchar (100)
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here

/* Get Client's Residence */

select dbo.GetClientFullName(s.FirstName, s.MiddleInit, s.LastName) StaffName, 
dbo.GetStaffTitlesById(s.Id) StaffTitle,
dbo.GetClientFullName(c.FirstName, c.MiddleInit, c.LastName) ClientName, 
dbo.GetAddressByEntityNameAndId('Client', c.Id) ClientAddress

from ClientStaff cs 
left outer join Staff s on cs.StaffId = s.Id 
left outer join Client c on cs.ClientId = c.Id

END

这是 UDF:

ALTER FUNCTION [dbo].[GetAddressByEntityNameAndId] 
(
-- Add the parameters for the function here
@entityName varchar (100),
@parentEntityId int
)
RETURNS varchar(300)
AS
BEGIN
-- Declare the return variable here
DECLARE @Address varchar(300)

if(@entityName = 'Client')
BEGIN

    select @Address = ca.Address + ' ' + ca.City + ' ' + ca.State + ' ' + ca.ZipCode
    from Client cc 
    inner join  ContactAddress ca on ca.ParentEntityId = cc.Id 
    inner join EntityName en on en.Id = ca.EntityNameId and en.Name = cc.Id 
    inner join GeneralLookup gl on ca.glAddressTypeId = gl.Id and gl.LookupItem = 'Primary' 
    where cc.Id = @parentEntityId

END 
-- Return the result of the function
RETURN @Address

END

我正在执行 SP 并收到错误: Conversion failed when converting the varchar value 'Client' to data type int. 我无法解决问题。有什么帮助吗?

【问题讨论】:

【参考方案1】:

您不能在 from 子句中使用 @entityName 代替表名。由于您仅在 Staff 上进行测试,因此您可以改用 from Staff cc。我知道在from 子句中有一个变量表名的唯一方法是使用动态SQL。而且我认为您不能在函数中使用动态 SQL。

在此处了解更多关于动态查询的信息http://www.sommarskog.se/dynamic_sql.html

【讨论】:

没有其他选择吗?我想使用参数,以便我可以删除这个 IF。否则我将不得不使用很多 IF 条件。 @asma – 除了动态 SQL 之外别无他物。 其实我没有太多时间去学习新东西。是不是很容易学,还是我得花点时间学习? @asma – 查看答案中的链接。这部分是关于动态表名的。 sommarskog.se/dynamic_sql.html#objectnames @asma – 如果没有表定义,我无法判断。不过这个看起来很可疑。 en.Name = cc.Id

以上是关于在 UDF from 子句中使用参数的主要内容,如果未能解决你的问题,请参考以下文章

SQL 用户定义函数是不是支持 SELECT 子句?

为啥不能在 Redshift 的 CTE 的某些子句中调用不可变的 UDF?

如何在 on 子句中使用自定义 udf 时模仿 hive 中的“not in”操作?

MySQL UDF 仅适用于 `IF` 中的 `WHERE` 子句

为啥在 CTE 中的 WHERE 子句之前执行 UDF 调用?

HQL,我可以参数化 FROM 子句吗?