3

注意:我在 SQL Server 2008 R2 下运行...

我花时间阅读了该站点和其他站点上有关如何执行查询超过 4000 个字符的动态 SQL 的数十篇文章。我已经尝试了十几种提出的解决方案。共识似乎是将查询拆分为 4000 个字符的变量,然后执行以下操作:

EXEC (@SQLQuery1 + @SQLQuery2)

这对我不起作用 - 查询在@SQLQuery1 末尾被截断。

现在,我已经看到了人们如何通过使用 REPLICATE 一堆空格等来“强制”进行长查询的示例,但这是一个真正的查询 - 但它比这更复杂一些。

我有名为“Company_A_ItemView”的 SQL 视图。

我有 10 家公司,我想用不同的名称创建完全相同的视图,例如“Company_B_ItemView”“Company_C_ItemView”等。

如果你提供帮助,请不要问为什么会有多个视图——只要接受我需要这样做,好吗?

每个公司都有自己的一组表,CREATE VIEW 语句按名称引用多个表。这是简要示例,但请记住,查询的总长度约为 6000 个字符:

CREATE view [dbo].[Company_A_ItemView] as  
select  
WE.[Item No_],  
WE.[Location Code],   
    LOC.[Bin Number],  
[..more fields, etc.]  
from  
[Company_A_Warehouse_Entry] WE  
left join  
[Company_A_Location] LOC  

...你明白了

所以,我目前正在做的是:

一个。将 CREATE VIEW 语句的内容拉入 2 个声明的变量中,例如

Set @SQLQuery1 = (select text 
                  from syscomments 
                  where ID = 1382894081 and colid = 1)  
Set @SQLQuery2 = (select 
                  from syscomments 
                  where ID = 1382894081 and colid = 2)

请注意,这是 SQL 存储长定义的方式 - 当您创建视图时,它将文本存储到多个 syscomments 记录中。在我的例子中,视图被分成 3591 个字符的文本块到第一个 syscomment 记录中,其余文本在第二个记录中。我不知道为什么 SQL 不使用 syscomment 字段中的所有 4000 个字符。并且语句在一个单词的中间被打破。

请注意,在我的所有示例中,所有 @SQLQueryxxx 变量都声明为 varchar(max)。我还尝试将它们声明为 nvarchar(max) 和 varchar(8000) 和 nvarchar(8000) ,结果相同。

湾。然后我对“Company_A”进行“搜索和替换”并将其替换为“Company_B”。在下面的代码中,变量“@CompanyID”首先设置为“Company_B”:

SET @SQLQueryNew1 = @SQLQuery1   
SET @SQLQueryNew1 = REPLACE(@SQLQueryNew1, 'Company_A', @CompanyID)  
SET @SQLQueryNew2  = @SQLQuery2   
SET @SQLQueryNew2 = REPLACE(@SQLQueryNew2, 'Company_A',@CompanyID)

C。然后我尝试:

EXEC (@SQLQueryNew1 + @SQLQueryNew2)

返回的消息表明它正在尝试执行在@SQLQueryNew1 末尾被截断的语句,例如查询文本的80%(大约)。

我已经尝试将最终结果转换为新的 varchar(max) 和 nvarchar(max) - 不走运 我已经尝试将原始查询转换为新的 varchar(max) 和 nvarchar(max) - 不走运

我查看了检索原始 CREATE VIEW 语句的结果,这很好。

我尝试了各种其他方法来检索原始 CREATE VIEW 语句,例如:

Set @SQLQuery1 = (select VIEW_DEFINITION) 
                  FROM [MY_DATABASE].[INFORMATION_SCHEMA].[VIEWS] 
                  where TABLE_NAME = 'Company_A_ItemView')`

这个只返回 CREATE VIEW 的前 4000 个字符

Set @SQLQuery1 = (SELECT (OBJECT_DEFINITION(@ObjectID))

如果我做一个

SELECT LEN(OBJECT_DEFINITION(@ObjectID))

它返回查询的正确长度(例如 5191),但是如果我查看@SQLQuery1,或者尝试

EXEC(@SQLQuery1), the statement is still truncated.

C。有一些参考资料指出,由于我在检索查询文本后对其进行操作,因此结果变量随后被截断为 4000 个字符。我尝试在执行 REPLACE 时对结果进行 CAST,例如

SET @SQLQueryNew1 = SELECT (CAST(REPLACE(@SQLQueryNew1, 
                                 'Company_A', 
                                 @CompanyID) AS varchar(max))

结果相同。

我知道还有其他方法,例如创建用于创建视图的存储过程。但是视图正在开发中,并且有些“不断变化”,因此将 CREATE VIEW 的文本放在存储过程中是很麻烦的。我的目标是能够获取 Company_A 的视图并准确复制它 - 多次,除了引用 Company_B 的视图名称和表名称、Company_C 的视图名称和表名称等。

我想知道是否有人对长 SQL“CREATE VIEW”语句进行了这种类型的操作并尝试执行它。

4

2 回答 2

6

只需使用VARCHAR(MAX)NVARCHAR(MAX)。它们适用于EXEC(string)


供参考,

请注意,这是 SQL 存储长定义的方式 - 当您创建视图时,它将文本存储到多个 syscomments 记录中。

这是不正确的。这是过去在 SQL Server 2000 上完成的方式。从 SQL Server 2005 及更高版本开始,它们在sys.sql_modules的单个条目中保存为 NVARCHAR(MAX) 。

syscomments仍然存在,但它保留为只读只是为了兼容。


所以你需要做的就是改变你的@SQLQuery1,2等。变量到单个 NVARCHAR(MAX) 变量,并从 sys.sql_modules 表的 [definition] 列中提取您的视图代码。

请注意,您应该小心您的字符串操作,因为如果所有输入参数都不是 (N)VARCHAR(MAX),则某些函数将恢复为 (N)VARCHAR(4000) 输出。(对不起,我不知道是哪一个,但 REPLACE() 可能是其中一个)。事实上,这可能是在您的测试中造成如此多混乱的原因。

于 2012-04-22T20:17:15.610 回答
0

声明您的 sql 变量 (@SQLQuery1...),nvarchar(4000) 确保每个 sql 部分不超过 4000 字节(将每个部分复制到文本文件并测试文件大小(以字节为单位))

于 2014-03-12T10:09:13.047 回答