SQL Server:找不到数据类型-错误仅在较大的脚本内发生

时间:2018-10-21 21:23:25

标签: sql sql-server types sqldatatypes sql-server-2017

我正在创建UDF。
如果我自己运行CREATE FUNCTION块,则会成功创建该函数。

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

USE MyDBSET ANSI_NULLSSET QUOTED_IDENTIFIER在两种情况下都是相同的,并且无效。

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

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

如果删除数据库,然后重新运行完整的数据库创建脚本,则在此行之前没有收到任何错误,并且仍然收到有关此数据类型无效的相同错误消息。

可能是什么原因造成的?
如果要“修复”完整的数据库创建脚本,应该从哪里开始?

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. */

enter image description here

在完整的数据库创建脚本中,这是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

2 个答案:

答案 0 :(得分:2)

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

要调试此问题,我将在SSMS中加载完整的查询,并在顶部添加BEGIN TRANSACTION。在下一行放入-- ROLLBACK。当查询失败时,您可以回滚,并以最小的伤害返回到干净状态(空db)。

基本上,刚开始删除发生故障的功能所不需要的内容。删除一些DDL语句,测试正在运行的事务并回滚事务,直到它运行无误为止。如果该代码正常运行,则可能是您删除的最后一段代码导致了问题。

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

像搜索一样对待它。删除单个DDL语句时,使查询生效,您已找到了罪魁祸首。您只需要找到该语句即可。

通过足够多的来回操作,您应该能够识别出引起您问题的代码块,希望是一条DDL语句。如果不是立即明白为什么那段代码会引起您的痛苦,请在此处或在新问题中发布它,并希望其他人会比我有帮助。

答案 1 :(得分:1)

user5151179发布的调试方法非常有用。
这是验尸,可能会帮助其他人在类似情况下缩小问题范围。

此问题是由包含脚本文件的DB脚本引起的,该脚本/脚本是在问题函数之前创建的(不是 ,并且未引用任何本机编译的模块)。

我仍然不知道为什么为什么发生,但是将数十个本机编译的函数移动到脚本中的另一个“位置”(靠近底部,最重要的是之后问题功能的创建)可以完全解决问题,而无需修改任何功能或过程。

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

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

如果有人对为什么SQL Server在创建本机编译的函数和过程时如此挑剔的想法有任何见识,请随时发表评论或发表其他答案。