我正在创建UDF。
如果我自己运行CREATE FUNCTION
块,则会成功仅创建该函数。
如果我将CREATE FUNCTION
块包含在一个更大的“完整”数据库创建脚本中,则会收到一条奇怪的错误消息,指出使用了无效的数据类型。
(请参见下面的代码块和错误屏幕截图。)
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. */
在完整的数据库创建脚本中,这是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
答案 0 :(得分:2)
这不会是一个很好的答案,但是这里...
要调试此问题,我将在SSMS中加载完整的查询,并在顶部添加BEGIN TRANSACTION
。在下一行放入-- ROLLBACK
。当查询失败时,您可以回滚,并以最小的伤害返回到干净状态(空db)。
基本上,刚开始删除发生故障的功能所不需要的内容。删除一些DDL语句,测试正在运行的事务并回滚事务,直到它运行无误为止。如果该代码正常运行,则可能是您删除的最后一段代码导致了问题。
如果要删除多个DDL语句(我会这样做),则此时可以更细化。我的意思是,删除一大堆函数不依赖的东西,然后运行整个查询。如果可行,请回滚,然后将该块重新添加回((Undo / Ctrl Z)),然后更细致地删除较小的块,一次删除一个,直到删除单个语句。
像搜索一样对待它。删除单个DDL语句时,使查询生效,您已找到了罪魁祸首。您只需要找到该语句即可。
通过足够多的来回操作,您应该能够识别出引起您问题的代码块,希望是一条DDL语句。如果不是立即明白为什么那段代码会引起您的痛苦,请在此处或在新问题中发布它,并希望其他人会比我有帮助。
答案 1 :(得分:1)
user5151179发布的调试方法非常有用。
这是验尸,可能会帮助其他人在类似情况下缩小问题范围。
此问题是由包含脚本文件的DB脚本引起的,该脚本/脚本是在问题函数之前创建的(不是 ,并且未引用任何本机编译的模块)。
我仍然不知道为什么为什么发生,但是将数十个本机编译的函数移动到脚本中的另一个“位置”(靠近底部,最重要的是之后问题功能的创建)可以完全解决问题,而无需修改任何功能或过程。
数据库中的每个对象都与以前完全相同,只是创建顺序不同。
这让我感到困惑,因为在这些对象之间没有引用,这将要求它们以特定顺序创建-对于UDTT,错误本身只是数据类型错误,它位于最顶端我的脚本,实际上是在数据库中的其他任何对象之前创建的。
如果有人对为什么SQL Server在创建本机编译的函数和过程时如此挑剔的想法有任何见识,请随时发表评论或发表其他答案。