Sql 如果从存储过程中执行更新字符串查询,则会引发错误
我有一个动态编译的update查询,里面有一堆语句。现在,语法似乎是正确的,正如我所能做的那样,在一个新的查询窗口(SSMS)中执行相同的字符串,没有返回任何错误,并且表中确实进行了更改。i、 eSql 如果从存储过程中执行更新字符串查询,则会引发错误,sql,.net,sql-server,sql-server-2008,tsql,Sql,.net,Sql Server,Sql Server 2008,Tsql,我有一个动态编译的update查询,里面有一堆语句。现在,语法似乎是正确的,正如我所能做的那样,在一个新的查询窗口(SSMS)中执行相同的字符串,没有返回任何错误,并且表中确实进行了更改。i、 e SELECT @updatequerystring = ' UPDATE ##Details SET [FieldName] = (Replace ( Replace
SELECT @updatequerystring =
' UPDATE ##Details
SET [FieldName] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( FieldName, Char(92),''___reversesolidusChar___'')
, Char(91),''___leftsquarebracketChar___'')
, Char(59),''___Semicolon___'')
, Char(58),''___ColonChar___'')
, Char(47),''___SolidusChar___'')
, Char(46),''___fullstopChar___'')
, Char(44),''___CommaChar___'')
, Char(39),''___apostropheChar___'')
, Char(34),''___DoubleQuotesChar___'')
, Char(32),''___SpaceChar___'') )
; UPDATE ##Details
SET [Response] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Response, Char(92),''___reversesolidusChar___'')
, Char(91),''___leftsquarebracketChar___'')
, Char(59),''___Semicolon___'')
, Char(58),''___ColonChar___'')
, Char(47),''___SolidusChar___'')
, Char(46),''___fullstopChar___'')
, Char(44),''___CommaChar___'')
, Char(39),''___apostropheChar___'')
, Char(34),''___DoubleQuotesChar___'')
, Char(32),''___SpaceChar___'') ) ; '
EXEC sp_executesql @updatequerystring
但是,当我设置要执行的相同字符串时,在与上面完全相同的was中,仅从我的查询中执行,将引发以下错误
.Net SqlClient数据提供程序:Msg 50000,级别15,状态1,过程
GenerateActivitiesQuestionResponseResultSet,第251行语法不正确
在“更新##详细信息集[字段名]=”附近(
替换(替换)替换(替换)替换(替换)
当我尝试只执行上面两条update语句中的一条时,会引发相同的错误。如果您能帮我解决这个问题,我将不胜感激。提前谢谢您。我重新格式化了您的查询,使其更具可读性
select @updatequerystring = '
UPDATE ##Details SET [FieldName] = (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace ( FieldName, Char(92),''___reversesolidusChar___'') ,
Char(91),''___leftsquarebracketChar___'') ,
Char(59),''___Semicolon___'') ,
Char(58),''___ColonChar___'') ,
Char(47),''___SolidusChar___'') ,
Char(46),''___fullstopChar___'') ,
Char(44),''___CommaChar___'') ,
Char(39),''___apostropheChar___'') ,
Char(34),''___DoubleQuotesChar___'') ,
Char(32),''___SpaceChar___'') ) ;
UPDATE ##Details SET [Response] = (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace (
Replace ( Response, Char(92),''___reversesolidusChar___'') ,
Char(91),''___leftsquarebracketChar___'') ,
Char(59),''___Semicolon___'') ,
Char(58),''___ColonChar___'') ,
Char(47),''___SolidusChar___'') ,
Char(46),''___fullstopChar___'') ,
Char(44),''___CommaChar___'') ,
Char(39),''___apostropheChar___'') ,
Char(34),''___DoubleQuotesChar___'') ,
Char(32),''___SpaceChar___'') ) ; '
注意到您正在尝试执行2条update语句—只使用一条语句进行尝试
尝试此操作,将两个更新更改为一个(这是您所需要的,因为您只更新一个表):
从SSMS内部可以运行多个查询,但从外部则无法运行。因此,当您搜索“在一条语句中更新多个表”时,会出现多个结果,我打赌(目前无法访问SSMS),这个答案可能适合您:现在这似乎有点激进,但请尝试运行以下命令:
declare @updatequerystring nvarchar(4000) = ''
print '1: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + 'UPDATE ##Details '
set @updatequerystring = @updatequerystring + 'SET [FieldName] = (Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
print '2: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
print '3: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( FieldName, Char(92),''___reversesolidusChar___'') '
set @updatequerystring = @updatequerystring + ', Char(91),''___leftsquarebracketChar___'') '
set @updatequerystring = @updatequerystring + ', Char(59),''___Semicolon___'') '
set @updatequerystring = @updatequerystring + ', Char(58),''___ColonChar___'') '
print '4: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + ', Char(47),''___SolidusChar___'') '
set @updatequerystring = @updatequerystring + ', Char(46),''___fullstopChar___'') '
set @updatequerystring = @updatequerystring + ', Char(44),''___CommaChar___'') '
set @updatequerystring = @updatequerystring + ', Char(39),''___apostropheChar___'') '
set @updatequerystring = @updatequerystring + ', Char(34),''___DoubleQuotesChar___'') '
print '5: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + ', Char(32),''___SpaceChar___'') ); '
set @updatequerystring = @updatequerystring + 'UPDATE ##Details '
set @updatequerystring = @updatequerystring + 'SET [Response] = (Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
print '6: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
print '7: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Replace '
set @updatequerystring = @updatequerystring + '( Response, Char(92),''___reversesolidusChar___'') '
set @updatequerystring = @updatequerystring + ', Char(91),''___leftsquarebracketChar___'') '
set @updatequerystring = @updatequerystring + ', Char(59),''___Semicolon___'') '
print '8: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + ', Char(58),''___ColonChar___'') '
set @updatequerystring = @updatequerystring + ', Char(47),''___SolidusChar___'') '
set @updatequerystring = @updatequerystring + ', Char(46),''___fullstopChar___'') '
set @updatequerystring = @updatequerystring + ', Char(44),''___CommaChar___'') '
set @updatequerystring = @updatequerystring + ', Char(39),''___apostropheChar___'') '
print '9: ' + cast(len(@updatequerystring) as varchar(20))
set @updatequerystring = @updatequerystring + ', Char(34),''___DoubleQuotesChar___'') '
set @updatequerystring = @updatequerystring + ', Char(32),''___SpaceChar___'') );'
print 'final: ' + cast(len(@updatequerystring) as varchar(20))
exec(@updatequerystring)
上周我遇到了一个问题,当将变量的值设置为某个动态SQL时,即使我使用的是nvarchar(max),它也会丢失数据作为我添加数据的变量。结果是SQL无法同时将变量值设置为超过x个字符,因此我必须将其分解为块,对于您的,我已将其逐行设置,因为它要短得多。此外,我还添加了一些LEN行,以便您可以检查动态SQL是否达到了正确的长度th
这一切都与您在SQL 2012 Enterprise中为我提供的原始版本一致,但我认为此诊断将帮助您检查变量是否已正确设置……在我刚才所想的所有消息之后,为什么不在执行之前从您的过程中打印出来呢
以下是我在上面示例中的输出:
1: 0
2: 77
3: 127
4: 289
5: 456
6: 557
7: 607
8: 748
9: 908
final: 978
问候
Liam我们可以看出的一件事是变量@updatequerystring正在被截断。根据提供的信息,这不应该发生。因此,我们需要更多信息来继续。对于进一步的故障排除,我建议如下:
编辑:您正在提取的错误不是来自SSMS。如果您确实在SSMS中收到错误,请将其包括在内好吗?请注意,即使变量声明为varchar(max),连接也会切断长varchar数据类型的结尾。这是因为文字字符串被视为varchar(8000)或nvarchar(4000)默认情况下。如果串联导致较大的字符值,则此数据类型不会更改。您需要显式转换为varchar(max)或nvarchar(max)以获得所需的结果。请参见以下有点尴尬的示例:
DECLARE @updatequerystring VARCHAR(MAX)
, @updatequerystring2 VARCHAR(MAX)
SELECT @updatequerystring = 'SELECT Replace ( ' + REPLICATE( 'A', 8123 ) + ', ' + REPLICATE( 'B', 8123 ) + ''''
, @updatequerystring2 = CONVERT( VARCHAR(MAX),
'SELECT Replace ( ' ) + REPLICATE( 'A', 8123 ) + ', ' + REPLICATE( 'B', 8123 ) + ''''
SELECT LEN( @updatequerystring ) AS StringLength -- 8000
, LEN( @updatequerystring2 ) AS StringLength2 -- 16020
开始消除过程: 1) 验证在SSMS中执行的字符串与“在您的查询中”执行的字符串是否相同。为此,您可以创建如下表:
CREATE TABLE dbo.TempQueryString (ID INT PRIMARY KEY, QueryString NVARCHAR(MAX))
在SSMS代码中,记录@updatequerystring变量。
e、 g
从“在您的查询”代码中,再次记录变量。
e、 g
要验证查询字符串是否相同,请运行以下操作:
DECLARE @Q1 NVARCHAR(MAX) = (select QueryString from dbo.TempQueryString WHERE ID = 1)
DECLARE @Q2 NVARCHAR(MAX) = (select QueryString from dbo.TempQueryString WHERE ID = 2)
IF @Q1 = @Q2
print 'Q1 equal to Q2'
else
print 'Q1 not equal to Q2'
IF CAST(@Q1 as varbinary(max)) = CAST(@Q2 as varbinary(max))
print 'Q1 equal to Q2 (binary comparison)'
else
print 'Q1 not equal to Q2 (binary comparison)'
让我们知道这是如何进行的。您的代码运行得很好,如果您运行下面的示例,您可以看到,在这个示例中,我使用一行数据创建了一个全局临时表:
DECLARE @updatequerystring NVARCHAR(MAX),
@fieldName VARCHAR(50) = 'field-[];."',
@response VARCHAR(50) = 'response-[];."'
SELECT @fieldName AS FieldName ,
@response AS Response
INTO ##Details
SELECT @updatequerystring = '
UPDATE ##Details
SET [FieldName] = ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(FieldName,
CHAR(92),
''___reversesolidusChar___''),
CHAR(91),
''___leftsquarebracketChar___''),
CHAR(59),
''___Semicolon___''),
CHAR(58),
''___ColonChar___''),
CHAR(47),
''___SolidusChar___''),
CHAR(46),
''___fullstopChar___''),
CHAR(44),
''___CommaChar___''),
CHAR(39),
''___apostropheChar___''),
CHAR(34), ''___DoubleQuotesChar___''),
CHAR(32), ''___SpaceChar___'') );
UPDATE ##Details
SET [Response] = ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(Response,
CHAR(92),
''___reversesolidusChar___''),
CHAR(91),
''___leftsquarebracketChar___''),
CHAR(59),
''___Semicolon___''),
CHAR(58),
''___ColonChar___''),
CHAR(47),
''___SolidusChar___''),
CHAR(46),
''___fullstopChar___''),
CHAR(44),
''___CommaChar___''),
CHAR(39),
''___apostropheChar___''),
CHAR(34), ''___DoubleQuotesChar___''),
CHAR(32), ''___SpaceChar___'') ); '
EXEC sp_executesql @updatequerystring
SELECT * FROM ##Details
DROP TABLE ##Details
这让我相信问题将出现在您的全局临时表及其架构中。因此,您的代码正在用比所替换的值长得多的字符串替换一堆特殊字符,因此我认为潜在的错误(似乎被Msg 50000
隐藏)将尝试使用不适合目标的值更新字段
如果从代码中运行以下命令,则应获取全局临时表的架构:
exec tempdb..sp_help '##Details'
检查您正在更新的字段的类型和长度,我猜目标字段的长度将是固定的(如未设置为最大值)。如果是,请增加到
max
,然后重新测试。一个建议,而不是真正的答案(这不适合注释),临时修改您的代码,如下所示:
PRINT '-----------------------------'
PRINT @updatequerystring
PRINT '-----------------------------'
EXEC sp_executesql @updatequerystring
准确查看SQL试图运行的查询。通读您的问题和注释,我觉得问题不是SQL问题,而是.NET问题 你能吗
- 复制粘贴创建连接和命令并执行它的代码?(我对如何创建大型更新字符串并不感兴趣,只对如何将其传递给ADO.Net对象感兴趣)
- 复制粘贴传递给服务器的确切字符串(不需要额外的“fluff”在SSMS中测试它,实际上就是传递给例如CommandText的内容)
UPDATE myTable
SET field1 = some_formula(field1),
field2 = some_formula(field2)
不需要将其拆分为两个操作。这样,服务器只需对数据进行一次检查,即可使其速度(书面)提高一倍。每个人似乎都能很好地运行您的代码,因此我认为问题可能不在动态语句中,而可能是权限问题或其他问题
exec tempdb..sp_help '##Details'
PRINT '-----------------------------'
PRINT @updatequerystring
PRINT '-----------------------------'
EXEC sp_executesql @updatequerystring
UPDATE myTable
SET field1 = some_formula(field1),
field2 = some_formula(field2)
DECLARE @updatequerystring NVARCHAR(4000) =
N'UPDATE ##Details
SET [FieldName] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( FieldName,''\'',''___reversesolidusChar___'')
, ''['',''___leftsquarebracketChar___'')
, '';'',''___Semicolon___'')
, '':'',''___ColonChar___'')
, ''/'',''___SolidusChar___'')
, ''.'',''___fullstopChar___'')
, '','',''___CommaChar___'')
, '''''''',''___apostropheChar___'')
, ''"'',''___DoubleQuotesChar___'')
, '' '',''___SpaceChar___'') )
; UPDATE ##Details
SET [Response] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Response,''\'',''___reversesolidusChar___'')
, ''['',''___leftsquarebracketChar___'')
, '';'',''___Semicolon___'')
, '':'',''___ColonChar___'')
, ''/'',''___SolidusChar___'')
, ''.'',''___fullstopChar___'')
, '','',''___CommaChar___'')
, '''''''',''___apostropheChar___'')
, ''"'',''___DoubleQuotesChar___'')
, '' '',''___SpaceChar___'') )'
EXEC (@updatequerystring);
--EXEC sp_executesql @updatequerystring;
UPDATE ##Details
SET [FieldName] = dbo.fnCleanInput([FieldName]),
[Response] = dbo.fnCleanInput([Response]);
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.fnCleanInput
(
@Input VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
IF (@Input IS NULL)
RETURN NULL;
-- NOTE: This could be stored in a lookup table and done with a CURSOR. Advantage being, you'd just have to update a lookup table instead of updating your code.
SET @Input = REPLACE(@Input, Char(92), ___reversesolidusChar___);
SET @Input = REPLACE(@Input, Char(91), ___leftsquarebracketChar___);
SET @Input = REPLACE(@Input, Char(59), ___Semicolon___);
SET @Input = REPLACE(@Input, Char(58), ___ColonChar___);
SET @Input = REPLACE(@Input, Char(47), ___SolidusChar___);
SET @Input = REPLACE(@Input, Char(46), ___fullstopChar___);
SET @Input = REPLACE(@Input, Char(44), ___CommaChar___);
SET @Input = REPLACE(@Input, Char(39), ___apostropheChar___);
SET @Input = REPLACE(@Input, Char(34), ___DoubleQuotesChar___);
SET @Input = REPLACE(@Input, Char(32), ___SpaceChar___);
RETURN @Input;
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.fnCleanInput2
(
@Input VARCHAR(MAX),
@Replacements VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
IF (@Input IS NULL)
RETURN NULL;
-- Note: I've left the function dbo.fnSplitReplacements out because this is theoretical and is dependant upon the delimitted format of @Replacements.
DECLARE @ToReplace VARCHAR(50),
@ReplaceWith VARCHAR(50);
DECLARE Replacements CURSOR FORWARD_ONLY FOR
SELECT
ToReplace,
ReplaceWith
FROM dbo.fnSplitReplacements(@Replacements);
OPEN Replacements;
FETCH Replacements INTO @ToReplace, @ReplaceWith;
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET @Input = REPLACE(@Input, @ToReplace, @ReplaceWith);
FETCH Replacements INTO @ToReplace, @ReplaceWith;
END
CLOSE Replacements;
DEALLOCATE Replacements;
RETURN @Input;
END
GO
declare @updatequerystring as nvarchar(max)
create table ##Details
(
FieldName nvarchar(50) ,
Response nvarchar(50) ,
)
insert into ##Details values('aaaaa','bbbbb')
SELECT @updatequerystring =
' UPDATE ##Details
SET [FieldName] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( FieldName, Char(92),''___reversesolidusChar___'')
, Char(91),''___leftsquarebracketChar___'')
, Char(59),''___Semicolon___'')
, Char(58),''___ColonChar___'')
, Char(47),''___SolidusChar___'')
, Char(46),''___fullstopChar___'')
, Char(44),''___CommaChar___'')
, Char(39),''___apostropheChar___'')
, Char(34),''___DoubleQuotesChar___'')
, Char(32),''___SpaceChar___'') )
; UPDATE ##Details
SET [Response] = (Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Replace
( Response, Char(92),''___reversesolidusChar___'')
, Char(91),''___leftsquarebracketChar___'')
, Char(59),''___Semicolon___'')
, Char(58),''___ColonChar___'')
, Char(47),''___SolidusChar___'')
, Char(46),''___fullstopChar___'')
, Char(44),''___CommaChar___'')
, Char(39),''___apostropheChar___'')
, Char(34),''___DoubleQuotesChar___'')
, Char(32),''___SpaceChar___'') ) ; '
EXEC sp_executesql @updatequerystring
select * from ##Details
Drop table ##Details
declare @FieldName varchar(max);
set @FieldName = '
First \
Second [
Third ;
Fourth :
';
declare @Map table (ReplaceThis varchar(100) primary key, WithThis varchar(100));
insert into @Map
select '\', '___reversesolidusChar___' union all
select '[', '___leftsquarebracketChar___' union all
select ';', '___Semicolon___' union all
select ':', '___ColonChar___'; -- and so on...
select @FieldName = replace(@FieldName, ReplaceThis, WithThis)
from @Map
select @FieldName;