如何再次执行长动态查询(大于4000)字符

时间:2012-04-22 01:45:26

标签: sql-server dynamic sql-server-2008-r2 exec

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

我花时间在这个网站和其他网站上阅读了几十篇关于如何执行查询超过4000个字符的动态SQL的帖子。我已经尝试了十多种解决方案。共识似乎是将查询拆分为4000个字符的变量然后执行:

EXEC (@SQLQuery1 + @SQLQuery2)

这对我不起作用 - 查询在@ SQLQuery1结束时被截断。

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

我的SQL View名称为“Company_A_ItemView”。

我有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)

℃。然后我尝试:

EXEC (@SQLQueryNew1 + @SQLQueryNew2)

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

我已经尝试将最终结果CAST到新的varchar(max)和nvarchar(max) - 没有运气 我试过CAST'原始查询一个新的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.

℃。有一些参考文献表明,由于我在检索查询文本后操作它,因此生成的变量将被截断为4000个字符。我已经尝试过CAST的结果,就像我做REPLACE一样,例如

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

同样的结果。

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

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

2 个答案:

答案 0 :(得分:4)

只需使用 VARCHAR(MAX) NVARCHAR(MAX)。它们适用于 EXEC(字符串)


仅供参考,

  

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

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

syscomments 仍然存在,但它仅以兼容性保留为只读。


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

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

答案 1 :(得分:0)

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