代码之家  ›  专栏  ›  技术社区  ›  Giffyguy

SQL Server:找不到数据类型-错误只出现在较大的脚本中

  •  1
  • Giffyguy  · 技术社区  · 7 年前

    我正在创建UDF。
    如果我运行 create function block by itself,则成功创建函数 only.

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

    use mydb , set ansi_nulls ,and set quoted_identifier are identifier in both cases,and have no effect.

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

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

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

    是什么导致的?< BR> 如果我想“修复”完整的数据库创建脚本,我应该从哪里开始?

    使用mydb 去 将Ansi_Nulls设置为打开 去 打开带引号的标识符 去 创建函数[dbo]。[test\u floattonstring]() 返回@testsults表( [类别]nvarchar(max)不为空, [示例]nvarchar(max)不为空, [应输入]nvarchar(max)不为空, [实际]nvarchar(max)不为空, [区分大小写]位不为空, [公差]nvarchar(max)不为空, [差异]nvarchar(max)不为空, [通过]位不为空, [说明]nvarchar(max)不为空 ) 作为开始 declare@testdata[nstringtestdata];/*此处出错,请参见下面的屏幕截图*/ 插入到@testdata/*等中*/ < /代码>

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

    使用mydb 去 …*/ 创建类型[dbo]。[nstringtestdata]作为表( [类别][nvarchar](max)不为空, [示例][nvarchar](max)不为空, [应输入][nvarchar](max)不为空, [实际][nvarchar](max)不为空, [区分大小写][位]不为空, [公差][整数]不为空, [描述][nvarchar](max)不为空 ) 去 < /代码> <我包括 创建函数 在一个更大的“完整”数据库创建脚本中,我收到一条奇怪的错误消息,指出使用了无效的数据类型。
    (请参见下面的代码块和错误屏幕截图。)

    USE MyDB , SET ANSI_NULLS 和 SET 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 回复  |  直到 7 年前
        1
  •  2
  •   user5151179    7 年前

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

    为了调试这个,我将在SSMS中加载完整的查询,并添加 BEGIN TRANSACTION 在上面。在下一行放 -- ROLLBACK . 当查询失败时,您可以回滚,并以最小的创伤返回到干净状态(空数据库)。

    基本上,只需开始删除功能不需要的内容,因为这些内容会出现故障。删除一些DDL语句,测试运行并在运行过程中回滚事务,直到事务运行无误为止。当它毫无错误地运行时,很可能是您删除的最后一块代码导致了您的问题。

    如果您要删除多个DDL语句(我会这样做),那么此时您可以获得更详细的内容。我的意思是,删除一堆你的函数不依赖的东西,然后运行整个查询。如果可以,回滚,将该块添加回(undo/ctrl z),然后更细化地删除较小的块,一次删除一个,直到删除单个语句为止。

    像搜索一样对待它。当删除单个DDL语句使查询正常工作时,您发现了罪魁祸首。你只要找到那句话就行了。

    有了足够的来回性,您应该能够识别出导致您的问题的代码块,希望是单个DDL语句。如果这段代码为什么会让你感到悲伤还不是很明显,那么把它贴在这里或者贴在一个新的问题上,希望其他人能比我更有帮助。

        2
  •  1
  •   Giffyguy    7 年前

    用户5151179发布的调试方法非常有用。
    这是验尸报告,它可以帮助其他人在类似情况下缩小问题范围。

    此问题是由包含在问题函数(即 不 本机编译,不引用任何本机编译的模块)。

    我还是不知道 为什么 这种情况会发生,但将几十个本机编译的函数移动到脚本中的另一个“位置”(更接近底部,最重要的是 之后 创建问题函数)完全解决了问题,而不修改任何函数或过程。

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

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

    如果有人知道为什么SQL Server如此挑剔 什么时候? 创建本机遵从的功能和过程,您可以随意留下评论或发布其他答案。