无效的对象名称'User-Defined-Table-Type'

时间:2015-11-19 12:29:30

标签: sql sql-server tsql database-design sql-server-2008-r2

我收到错误:

Invalid object name 'UDTT_SuppliersList'.

用户定义的表类型为:

CREATE TYPE [dbo].[UDTT_SuppliersList] AS TABLE(
    [SupplierID] [int] NOT NULL,
    [Region_Name] [varchar](255) NULL,
    PRIMARY KEY CLUSTERED 
(
    [SupplierID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO

我正在使用它(传递参数)和StoredProcedures,它工作正常。但是今天我尝试将它作为参数传递给Table-Valued函数。表已成功创建且没有错误。但是,当我尝试调用该函数时,它给出了我上面提到的错误。

declare @tbl_UDTT_SuppliersList UDTT_SuppliersList 
--declare, and assume populated with data

select* from dbo.GetSupplierInvoicesByDate(@tbl_UDTT_SuppliersList)

这是功能代码:

ALTER FUNCTION [dbo].[GetSupplierInvoicesByDate]
(
    @tbl_UDTT_SuppliersList as dbo.UDTT_SuppliersList READONLY
)
RETURNS 
@tableList TABLE(
    SupplierID int,
    InvoiceAmount decimal(19, 3)
    )
AS
BEGIN
    INSERT INTO @tableList (
        SupplierID, 
        InvoiceAmount
    )

    SELECT 
    inv.SupplierID as SupplierID
    ,inv.Amount as InvoiceAmount
    FROM dbo.Invoices inv
    inner join UDTT_SuppliersList tSupp on tSupp.SupplierID = inv.SupplierID
    WHERE inv.IsPaidFully = 0

    RETURN
END

1 个答案:

答案 0 :(得分:1)

问题在于你的功能:

 SELECT 
     inv.SupplierID as SupplierID
    ,inv.Amount as InvoiceAmount
 FROM dbo.Invoices inv
 inner join UDTT_SuppliersList tSupp       -- use use type, not table variable
    on tSupp.SupplierID = inv.SupplierID

应该是:

SELECT 
     inv.SupplierID as SupplierID
     ,inv.Amount as InvoiceAmount
FROM dbo.Invoices inv
JOIN @tbl_UDTT_SuppliersList tSupp 
  ON tSupp.SupplierID = inv.SupplierID;

您可能想知道为什么SQL Server允许这样做,答案很简单 Deferred Name Resolution

  

创建存储过程时,过程中的语句   被解析为语法准确性。如果出现语法错误   在过程定义中遇到,返回错误并且   未创建存储过程。如果语句是语法上的   更正,存储过程的文本存储在   sys.sql_modules目录视图。

     

第一次执行存储过程时,查询   处理器从中读取存储过程的文本   sys.sql_modules目录视图并检查对象的名称   程序使用的程序存在。 此过程称为延迟   名称解析,因为存储的引用的表对象   创建存储过程时,不需要存在过程,但是   只有在执行时才会执行。

考虑使用内联语法以获得更好的性能:

ALTER FUNCTION [dbo].[GetSupplierInvoicesByDate](
    @tbl_UDTT_SuppliersList as dbo.UDTT_SuppliersList READONLY)
RETURNS  TABLE
AS
RETURN (SELECT 
         inv.SupplierID AS SupplierID
         ,inv.Amount AS InvoiceAmount
        FROM dbo.Invoices inv
        JOIN @tbl_UDTT_SuppliersList tSupp 
          ON tSupp.SupplierID = inv.SupplierID
        WHERE inv.IsPaidFully = 0);

我建议您阅读 Inline vs Multistatement Table Function