我可以使用以下代码进行微小的查询:
DECLARE @sql VARCHAR(8000)
SET @sql = 'SELECT * FROM myTable'
Exec @sql
上述方法对于维护大量代码非常有用,特别是当我们需要进行一次更改并将它们反映到任何地方时。
我的问题是我的查询(它只是一个单一的查询)我想要提供给@sql变量使用超过25个表连接,其中一些在临时表变量上,包含复杂的操作,因此它远远超过长度为8000个字符。
我希望使用TEXT数据类型来存储此查询,但MSDN会显示一条警告消息,Microsoft正计划从其下一版本中删除Text,NText和Image数据类型。我希望我的代码也能在将来运行。
我想过将这个查询存储在一个单独的文件中,但由于它使用表变量和其他特定于过程的参数的连接,我怀疑这是否可行。
请告诉我一个将大型查询存储到变量中并在过程中多次执行它的方法。
答案 0 :(得分:23)
如果你有连接的Unicode / nChar / nVarChar值,那么SQL Server将隐式地将你的字符串转换为VarChar(8000),遗憾的是它太愚蠢了,以至于它会截断你的字符串甚至给你一个警告数据已被截断!
当连接长字符串(或你感觉可能很长的字符串)总是预先连接你的字符串构建与 CAST(''作为nVarChar(MAX)),如下所示:< / p>
SET @Query = CAST('' as nVarChar(MAX))--Force implicit conversion to nVarChar(MAX)
+ 'SELECT...'-- some of the query gets set here
+ '...'-- more query gets added on, etc.
认为这就是SQL Server的工作方式真是太痛苦和可怕了。的:(强>
我知道网上的其他解决方法是说使用多个变量将代码分解为多个SET / SELECT分配,但鉴于上述解决方案,这是不必要的。
对于那些最多达到4000个字符的人来说,可能是因为你有Unicode,所以它被隐式转换为nVarChar(4000)。
说明:
幕后发生的事情是,即使您指定的变量使用(MAX),SQL Server也会评估您首先分配的值的右侧,默认为nVarChar(4000)或VarChar(8000)(取决于在你连接什么)。完成后计算出值(并在为你截断之后),然后在将其赋值给变量时将其转换为(MAX),但到那时为时已晚。
答案 1 :(得分:16)
如果您使用的是SQL Server 2008或更高版本,则可以使用VARCHAR(MAX)
DECLARE @sql VARCHAR(MAX)
答案 2 :(得分:6)
DECLARE @sql VARCHAR(max)
SET @sql = 'SELECT * FROM myTable'
Exec @sql
注意:
Print(@sql)
仅显示前8000个字符!
答案 3 :(得分:4)
问题是因为您的字符串默认限制为8000个符号。为防止这种情况,您应将其转换为(N)VARCHAR(MAX)
DECLARE @sql VARCHAR(8000)
SET @sql = CAST('SELECT * FROM myTable' AS VARCHAR(MAX))
--Check length of variable
PRINT 'Length is: '+CAST(LEN(@sql) AS VARCHAR)+ 'symbols'
Exec @sql
答案 4 :(得分:3)
使用
EXEC
(
'
--your sql script here
'
)
答案 5 :(得分:2)
我之前遇到过这种情况(在SQL 2005中),我可以告诉你,你有两个选择:
1 - 使用sys.sp_sqlexec存储过程,它可以采用类型文本的参数(IMO这是要走的路)。不要介意警告。在SQL 2008中,仍然支持ntext,如果在那里执行varchar(max),它将起作用。所以基本上,如果你有2008,文本解决方案和varchar(max)都可以工作,所以你有时间改变它= - )。但是在2012年,只有varchar(max)可以使用,因此您必须在升级之前更改它。
2-(这是我最初做的)检查这篇文章:http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=52274并做“Kristen”用户说的话。对我来说就像一个魅力。不要忘记将它们预先设置为空字符串。如果您了解我的帖子,您现在知道在SQL 2008或更新版本中这样做很傻。
答案 6 :(得分:2)
你应该阅读这篇文章的答案,该答案非常好地解释了这种情况: SQL NVARCHAR and VARCHAR Limits
nvarchar(x)
varchar(y)
nvarchar(max)
可以存储最多2GB。问题在于nvarchar(max) + varchar(y) = nvarchar(max) + nvarchar(4000)
;如果y大于4000且小于8000,则SQL会将varchar(y)
转换为nvarchar(y)
或nvarchar(4000)
,从而截断字符串!
答案 7 :(得分:1)
在你这样做的过程中,没有解决方案。从2012开始,MsSql支持Ntext,例如,它允许您在变量中超过8000个字符。解决此问题的方法是在表中创建多个变量或多行,您可以迭代。
最好使用MsSql版本,最新版本的变量的最大大小为8000个字符。所以,如果你正在处理一个说80,000个字符的字符串。您可以将数据解析为10个变量,每个变量8000个字符(8000 x 10 = 80,000),或者您可以将变量分成几部分并将其放入表格中,例如LongTable(Bigstring Varchar(8000))将10行插入此处并使用身份值,以便您可以按相同的顺序检索数据。
您正在尝试的方法目前不适用于MsSql。
另一个不起眼的选项是可行但不可取的是通过使用命令shell命令来读取/写入文件,将变量存储在文本文件中。然后你有超过8000个字符的空间。这比上述其他方法慢,安全性低。
答案 8 :(得分:0)
ALTER PROCEDURE [dbo].[spGetEmails]
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
declare @p varbinary(max)
set @p = 0x
declare @local table (col text)
SELECT @p = @p + 0x3B + CONVERT(varbinary(100), Email)
FROM tbCarsList
where email <> ''
group by email
order by email
set @p = substring(@p, 2, 10000000)
insert @local values(cast(@p as varchar(max)))
select col from @local
END
答案 9 :(得分:0)
我遇到了同样的问题,字符串被截断了。我了解到你可以多次执行sp_executesql语句。
由于我的代码块远远超过了4k / Max的限制,我将其分解为这样的小块:
set @statement = '
update pd
set pd.mismatchtype = 4
FROM [E].[dbo].[' + @monthName + '_P_Data] pd
WHERE pd.mismatchtype is null '
exec sp_executesql @statement
set @statement = 'Select * from xxxxxxx'
exec sp_executesql @statement
set @statement = 'Select * from yyyyyyy '
exec sp_executesql @statement
end
因此,只要每个块本身都在大小限制范围内,每个集合@Statement都可以拥有varchar(max)(为了节省空间,我在我的示例中删除了实际代码)
答案 10 :(得分:0)
我有同样的问题。我有一个超过21,000个字符的SQL。出于某些原因,
class Distance extends React.Component {
constructor(props) {
super(props);
this.state = {
distance: 0
};
}
onChange = e => {
this.setState({
distance: this.props.distance ? this.props.distance + e.target.value : e.target.value
});
}
render() {
return (
<div>
<p>{this.props.distance}</p>
<select onChange={this.onChange}>
<option value="30">30km</option>
<option value="50">50km</option>
<option value="70">70km</option>
</select>
</div>
);
}
}
会提出几个问题
我最终不得不将其平均分为多个变量,然后才起作用。
Declare @SQL VARCHAR(MAX)
EXEC(@SQL)
答案 11 :(得分:0)
在打印之前,请转换为演员表并更改数据类型。
PRINT CAST(@sql AS NTEXT)
现在,尝试一下。
答案 12 :(得分:0)
如果您要完成的工作是在Management Studio中执行此操作,则以下脚本可能会有所帮助。
DECLARE @Len INT = 5
DECLARE @Str VARCHAR(MAX) = '1111122222333334444455555'
DECLARE @TmpStr VARCHAR(MAX)
DECLARE @Return TABLE (RetStr VARCHAR(MAX))
WHILE(LEN(@Str) > 0)
BEGIN
SET @TmpStr = LEFT(@Str, @Len)
IF(LEN(@Str) > @Len)
SET @Str = RIGHT(@Str, LEN(@Str) - @Len)
ELSE
SET @Str = ''
INSERT INTO @Return SELECT @Str
END
SELECT * FROM @Return
@Len
应该为8000,因为这是Management Studio显示的最大长度。 @Str
是超过8000个字符的文本。