Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么NVarchar(MAX)不能使用SP_ExecuteSQL执行完整的动态查询?_Sql_Sql Server_Stored Procedures_Dynamic_Sp Executesql - Fatal编程技术网

为什么NVarchar(MAX)不能使用SP_ExecuteSQL执行完整的动态查询?

为什么NVarchar(MAX)不能使用SP_ExecuteSQL执行完整的动态查询?,sql,sql-server,stored-procedures,dynamic,sp-executesql,Sql,Sql Server,Stored Procedures,Dynamic,Sp Executesql,我创建了一个包含两个查询的存储过程,这两个查询将更新两个表中的记录 所以我会提到它显示了什么 我的程序如下 ALTER PROC UpdateMissingItemONPoe @StoreID INT, @Name VARCHAR(20) AS BEGIN DECLARE @UpdateRec NVARCHAR(MAX) = ''; DECLARE @StoreIP SYSNAME = '' SET @StoreIP = CASE @StoreID

我创建了一个包含两个查询的存储过程,这两个查询将更新两个表中的记录

所以我会提到它显示了什么

我的程序如下

ALTER PROC UpdateMissingItemONPoe 
    @StoreID INT,
    @Name VARCHAR(20)
AS
BEGIN
    DECLARE @UpdateRec NVARCHAR(MAX) = '';
    DECLARE @StoreIP SYSNAME = ''

    SET @StoreIP = CASE @StoreID 
                      WHEN 1111 THEN '[192.168.1.45].[Store1].[dbo]'
                      WHEN 2222 THEN '[192.168.2.45].[Store2].[dbo]'
                      WHEN 3333 THEN '[192.168.3.45].[Store3].[dbo]'
                   END
    SET @UpdateRec = N' IF((SELECT NameID from '+@StoreIP+'.Details WHERE Name = '''+@Name+''') = 2 )
BEGIN
    INSERT INTO ' + @StoreIP + '.PurchaseOrderEntry(
            /*  InsertField Name  */
        )

        select
            Name,
            Standard,
            Department,
            Category,
            SubDescription,
            Rank
        from
            '+@StoreIP+'.Details 
        where
            Name = '''+@Name+'''

        INSERT INTO '+@StoreIP+'.HeadQuarter(
            /*  InsertField Name  */
        )
        select
            Name,
            Standard,
            Department,
            Category,
            SubDescription,
            Rank
        from
            '+@StoreIP+'.Details 
        where
            Name = '''+@Name+'''
    END'

    print @UpdateRec
    EXEC sp_executesql @UpdateRec
END
当我执行此存储过程时,它不会显示任何错误消息。但是,当我打印时,动态查询没有完整的查询

打印的查询就像

INSERT INTO '+@StoreIP+'.PurchaseOrderEntry(
    /*  InsertField Name  */
)

select
    Name,
    Standard,
    Department,
    Category,
    SubDescription,
    Rank
from
    '+@StoreIP+'.Details 
where
    Name = '''+@Name+'''

INSERT INTO '+@StoreIP+'.HeadQuarter(
    /*  InsertField Name  */
)

select
    Name,
    Standard,
    Department,
    Category,     
其余的行丢失了

我将其改写为:

ALTER PROC UpdateMissingItemONPoe 
    @StoreID INT,
    @Name VARCHAR(20)
AS
BEGIN
    DECLARE @UpdateRec NVARCHAR(MAX) = N'';
    DECLARE @StoreIP NVARCHAR(128) = N'';

    SET @StoreIP = CASE @StoreID 
                      WHEN 1111 THEN '[192.168.1.45].[Store1].[dbo]'
                      WHEN 2222 THEN '[192.168.2.45].[Store2].[dbo]'
                      WHEN 3333 THEN '[192.168.3.45].[Store3].[dbo]'
                   END;

    SET @UpdateRec = N' IF((SELECT NameID from <@StoreIP>.Details 
                           WHERE Name = @Name) = 2 )
BEGIN
    INSERT INTO <StoreIP>.PurchaseOrderEntry(
            /*  InsertField Name  */
        )

        select
            Name,
            Standard,
            Department,
            Category,
            SubDescription,
            Rank
        from
            <@StoreIP>.Details 
        where
            Name = @Name

        INSERT INTO <@StoreIP>.HeadQuarter(
            /*  InsertField Name  */
        )
        select
            Name,
            Standard,
            Department,
            Category,
            SubDescription,
            Rank
        from
            <@StoreIP>.Details 
        where
            Name = @Name
    END';

   SET @UpdateRec = REPLACE(@UpadteRec, N'<@StoreIP>', @StoreIp);

    print @UpdateRec
    EXEC sp_executesql @UpdateRec, N'@Name NVARCHAR(20)', @Name;
END

使用参数化的动态SQL并使用替换而不是连接来交换表名。

您的查询肯定超过了4000个字符

将SET语句更改为

SET @UpdateRec = CONVERT(NVARCHAR(MAX), '') + N' IF(('

如果。。。到nvarcharmax

过去,如果这些多部分语句没有显式转换为nvarchar4000类型,SQL Server会将它们转换为nvarchar4000

如果你有一个变量

DECLARE @UpdateRec NVARCHAR(MAX) = '';
然后使用这种语法

SET @UpdateRec = N' IF((SELECT NameID from '+@StoreIP+'.Details WHERE
 Name = '''+@Name+''') = 2 ) BEGIN
 INSERT INTO ' + @StoreIP + '.PurchaseOrderEntry( (...)'

结果将无声地转换为nvarchar4000,并将在没有警告的情况下截断任何多余的字符。

@marc\s你知道吗?@UpdateRec的长度是多少?print@UpdateRec可能无法打印@UpdateRec中的所有内容,这取决于中的设置SSMS@Squirrel我提到过。这是NVarcharMAXCan无法在SQL Server 2016上复制的-打印输出正确地显示了@StoreIP被替换为案例中正确的预期值,并且输出包含所有行…@Liamneesan,不仅打印的查询被截断,IF语句丢失,变量未正确连接。您发布的代码将无条件地包含这些内容,并按预期为我运行。我怀疑你实际执行的程序与你问题中的程序不同。我按照你提到的那样做了。现在长度显示为4724。但它仍然没有显示完整的QuerySMS无法打印出完整的文本长度。我记得有一个最大长度,但我不记得了。要打印完整的查询,您需要执行substring并一次打印4000。但是您的查询执行了吗?该查询工作正常。现在我创建两个NVarcharMAX变量,并使用sp_executesql执行这些变量。它成功执行,记录被插入到我的表中。我只是试着在单个变量上只执行一次。它是k@Liamneesan那么请接受这个回答。这就是如此设计的工作原理;当提问者标记一个答案,以便其他人可以找到答案时,这会有所帮助。@SMor对不起,没有人告诉我的问题出在哪里,他们只是给了我另一种解决方法。我的问题怎么了?。。。甚至我也找到了另一种方法,并像他们发布的那样成功地执行了它。