Sql 如果从存储过程中执行更新字符串查询,则会引发错误

Sql 如果从存储过程中执行更新字符串查询,则会引发错误,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

我有一个动态编译的update查询,里面有一堆语句。现在,语法似乎是正确的,正如我所能做的那样,在一个新的查询窗口(SSMS)中执行相同的字符串,没有返回任何错误,并且表中确实进行了更改。i、 e

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正在被截断。根据提供的信息,这不应该发生。因此,我们需要更多信息来继续。对于进一步的故障排除,我建议如下:

  • 将@updatequerystring声明为VARCHAR(MAX)或NVARCHAR(MAX)
  • 使用EXEC(@updatequerystring)而不是EXEC sp_executesql@updatequerystring
  • 在EXEC(@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;