找不到数据类型 - 错误仅发生在较大的脚本中

Cannot find data type - error occurs only inside larger script

我正在创建一个 UDF。
该函数成功创建 ONLY 如果我 运行 CREATE FUNCTION 块本身。

如果我在更大的 "complete" 数据库创建脚本中包含 CREATE FUNCTION 块,我会收到一条奇怪的错误消息,指出使用了无效的数据类型。
(请参阅下面的代码块和错误屏幕截图。)

USE MyDBSET ANSI_NULLSSET QUOTED_IDENTIFIER 在这两种情况下是相同的,没有任何效果。

这很奇怪,因为 UDTT 是在数据库创建脚本中更早创建的,没有错误。我可以在 SSMS 中看到 UDTT,所以它显然存在......

如果我 re-run 完整的数据库创建脚本,我显然会收到一堆关于重新创建已经存在的对象的消息 - 我忽略了这些消息,因为这是预期的。
但是后来我得到了这个错误,导致这个特定的函数创建失败,这阻止了它之后的许多其他对象创建。

如果我删除数据库,re-run 完整的数据库创建脚本,我在这一行之前没有收到任何错误,我仍然收到关于此数据类型无效的相同错误消息。

可能是什么原因造成的?
如果我想 "repair" 完整的数据库创建脚本,我应该从哪里开始?

USE MyDB
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[Test_FloatToNString] ( )

RETURNS @TestResults TABLE (
                               [Category]      NVARCHAR ( MAX ) NOT NULL ,
                               [Example]       NVARCHAR ( MAX ) NOT NULL ,
                               [Expected]      NVARCHAR ( MAX ) NOT NULL ,
                               [Actual]        NVARCHAR ( MAX ) NOT NULL ,
                               [CaseSensitive] BIT              NOT NULL ,
                               [Tolerance]     NVARCHAR ( MAX ) NOT NULL ,
                               [Difference]    NVARCHAR ( MAX ) NOT NULL ,
                               [Passed]        BIT              NOT NULL ,
                               [Description]   NVARCHAR ( MAX ) NOT NULL
                           )
AS BEGIN

    DECLARE @testData [NStringTestData] ;   /* Error here, see screenshot below */

    INSERT INTO @testData   /* etc. */

在完整的数据库创建脚本中,UDTT 如下所示:

USE MyDB
GO

/* ... */

CREATE TYPE [dbo].[NStringTestData] AS TABLE(
    [Category] [nvarchar](max) NOT NULL,
    [Example] [nvarchar](max) NOT NULL,
    [Expected] [nvarchar](max) NOT NULL,
    [Actual] [nvarchar](max) NOT NULL,
    [CaseSensitive] [bit] NOT NULL,
    [Tolerance] [int] NOT NULL,
    [Description] [nvarchar](max) NOT NULL
)
GO

这不是一个好的答案,但这里...

为了调试它,我会在 SSMS 中加载完整的查询,并在顶部添加 BEGIN TRANSACTION。在下一行输入 -- ROLLBACK。当您的查询失败时,您可以回滚,并以最小的创伤结束回到干净状态(空数据库)。

基本上只是开始删除功能失败时不需要的内容。删除一些 DDL 语句,测试 运行ning 并边走边回滚事务,直到 运行s 没有错误。当它 运行 没有错误时,很可能是你删除的最后一段代码导致了你的问题。

如果您要删除多个 DDL 语句(我会这样做),此时您可以更细化。我的意思是,删除一大堆你的函数不依赖的东西,然后 运行 整个查询。如果可行,回滚,将该块添加回 (Undo/Ctrl Z),然后更精细地删除较小的块,一次一个,直到删除单个语句。

将其视为搜索。当删除单个 DDL 语句使您的查询正常工作时,您找到了罪魁祸首。你只需要找到那个声明。

通过足够多的来回检查,您应该能够识别导致问题的代码块,希望是单个 DDL 语句。如果不是很明显为什么那段代码让你感到悲伤,post 在这里或在一个新问题中,希望其他人会比我更有帮助。

user5151179 提供的调试方法post很有帮助。
这是 post-mortem,它可能会帮助其他人在类似情况下缩小问题范围。

此问题是由于在问题函数之前创建的包含本机编译 functions/procedures 的数据库脚本(不是 本机编译的,并且不引用任何本机已编译的模块)。

我仍然不知道为什么会发生这种情况,但是将几十个本机编译的函数移动到脚本中不同的 "location"(靠近底部,大多数重要的是创建问题函数之后)完全解决了问题,无需修改任何函数或程序。

数据库中的每个对象都与之前完全相同,只是创建顺序不同。

这让我感到困惑,因为这些对象之间没有任何引用,这将要求它们以特定顺序创建 - 而错误本身只是一个数据类型错误,对于位于在我的脚本的最顶部,在数据库中的任何其他对象之前创建。

如果有人知道为什么 SQL 服务器对 在创建 本机编译的函数和过程时如此挑剔,请随时发表评论或 post另一个答案。