无法使用 NVARCHAR(Max) 创建完整的动态查询
Unable to Create the Complete Dynamic Query using NVARCHAR(Max)
我正在使用 NVARCHAR(MAX)
创建动态 query.Since NVARCHAR
每个字符使用 2 个字节,NVARCHAR(MAX)
变量中可以包含大约 10 亿个字符 (Link Reference).
我尝试在 SQL 服务器本身中执行存储过程,然后通过应用程序执行存储过程。
这两种情况动态查询都是不超过那些字符长度的。但只有部分动态查询是获取 executed.Because 存储过程向应用程序抛出错误。
我是否遗漏了任何代码?
USE [MyDemoDB]
GO
ALTER PROCEDURE [dbo].[sp_Apply]
(
@scenarioId INT,
@userId INT,
@bookId INT
)
AS
DECLARE @BucketId INT
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @PlanningSeason NVARCHAR(20)
DECLARE @StructureId INT = 9
DECLARE @AllocStructureId INT = 11
DECLARE @UpdatedUser INT = 2
DECLARE @InsertOne NVARCHAR(MAX)=''
DECLARE @AreaSchema NVARCHAR(40)
DECLARE @AreaCode NVARCHAR(20)
DECLARE @EmptyValue NVARCHAR(20)
SET @AreaCode = ''
SET @AreaSchema = '[dbo]'
SET @InsertOne = '
DECLARE @FGSupplySeqId INT
DECLARE @FGSupplyId NVARCHAR(10)
DECLARE @PlannedQty DECIMAL(18,2)
DECLARE @ConfirmdQty DECIMAL(18,2)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @Season NVARCHAR(20)
DECLARE @MerchantId NVARCHAR(50)
DECLARE @UpdatedUser INT
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @BucketId INT
DECLARE @ProductNo NVARCHAR(100)
DECLARE @LocationNo NVARCHAR(100)
SET @BucketId = '+ CAST(@BucketId AS VARCHAR) + '
SET @UpdatedUser = '+ CAST(@userId AS VARCHAR) + '
IF @BucketId = 1
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ '
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year,Season,ProductNo,LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId NVARCHAR(10)
DECLARE @AllocStatus INT
SET @FGAllocationId = ''E''
SET @AllocStatus= 0
SELECT @FGAllocationId = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] IS NULL
IF @FGAllocationId = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FinishedGoodSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END
IF @BucketId = 2
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ 'AND Month IS NOT NULL
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year, Month,Season,@ProductNo,@LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId AND Month IS NOT NULL
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId1 NVARCHAR(10)
SET @FGAllocationId1 = ''E''
SELECT @FGAllocationId1 = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] = @Month
IF @FGAllocationId1 = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Month,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Month,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId1
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END'
print @InsertOne
EXEC(@InsertOne)
确保您的变量不包含引号或双引号。
declare @value nvarchar(100) = 'abcd''efgh'
declare @sql nvarchar(max)
-- tons of QUOTE !!!
Set @sql = N'select ''' + REPLACE(@value, '''', '''''') + '''';
print @sql
exec sp_executesql @sql
将您的对象名称用括号括起来,并在 into 和 DB:
之间至少加上一个 space
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
-- space is missing
或者您可以使用 QUOTENAME 函数 QUOTENAME(@AreaSchema)
使用 N'' 和 NVARCHAR(...) 或 '' 和 VARCHAR() 但不要混用
您将所有内容声明为 NVARCHAR,然后将其与 '' 连接。应该是N''。您还将 convert/cast 一切都作为 VARCHAR。它应该是 NVARCHAR(...)。
动态 SQL 使用 NVARCHAR 字符串。
确保变量已设置或具有默认值
SET @BucketId = '+ CAST(@BucketId AS nVARCHAR) + '
这将 return NULL,因为@BucketId 未在您的存储过程中设置。使用 ISNULL,设置它或给它一个默认值
您应该使用 EXEC sp_executesql 并在使用时声明变量
https://msdn.microsoft.com/fr-fr/library/ms188001(v=sql.120).aspx
EXEC sp_executesql @yourquery, N'@UserID int, ...', @userID = @UserId ...
仅在需要时保持串联(动态对象名称)
- 终于
在尝试执行它之前,请确保您的打印输出正确的查询(打印仅显示前 4000 个字符)。如果查询不完整,可能意味着您在停止处附近的代码中有错误。
我试过你的过程,但它 return 没有任何东西(NULL),除非我首先初始化所有变量。还有截断,因为你不使用 N''
是的,您可能遇到了这个问题,因为 nvarchar 的限制是 4000 个字符。
我也遇到这个问题,通过连接字符串然后执行来解决。
如果您 select 或打印它只显示 4000 个字符,但如果您连接或追加字符串,它必须追加(直到 8000 个字符)。所以不要为此烦恼,你不打印或 select 只是追加和执行它绝对有效。
在此这是解释。
declare @sql Nvarchar(max),
@a nvarchar(max),
@b nvarchar(max);
select @sql =N'', @a = N'a', @b = N'b';
select @sql = @sql +replicate(@a,4000) + replicate(@b, 6000);
select len(@sql)
为此有 one rule :-
SET @dynamicSQL = [concatenate various unicode strings and nvarchar
variables totalling over 4000 characters] -- MAKE SURE AT LEAST ONE OF
THE UNICODE STRINGS IS NVARCHAR(MAX), YOU CAN CAST ANY ONE ARGUMENT.
你也可以检查这个link。
已更新
我展示了你的整个代码,并想解释一些事情。
首先,为什么要动态查询。代码显示你可以在没有动态查询的情况下做到这一点,而且还有很多嵌套游标(尝试通过简单查询忽略它)
不过,如果你想去,那么我会删除你额外的代码(我不认为删除 space 会起作用,我有 4 个联合查询,它的长度非常大,它在单独验证每个部分后使用此策略 window)
在阅读下文之前,a.Here 是另一种选择。除了在查询中定义参数,您也可以传递此参数。
begin tran
create table table1 ( id int, value varchar(10) )
insert into table1 values( 1,'001')
insert into table1 values(2, '002')
insert into table1 values( 3,'003')
insert into table1 values( 4,'004')
declare @sql nvarchar(max) , @temp nvarchar(50) = '1,2,3', @tempIntSingleValue nvarchar(50) = '2'
select * from table1
set @sql = 'select * from table1 where id in ( ' + @temp + ')'
print @sql
exec sp_executesql @sql
set @sql = 'select * from table1 where id in ( @tempInner)'
print @sql
exec sp_executesql @sql , N'@tempInner int', @tempInner = @tempIntSingleValue
rollback
b。您在动态查询中使用了相同的参数。所以我认为你必须给出默认值或在 运行 时间分配值。所以在连接你的字符串时不会变成空。请参阅下面的示例。我将所有字符定义为 '' 并将 int 定义为数值,最后 print 打印一些东西。如果我们不定义它永远不会打印空白,因为连接设置了空值。
declare @scenarioId INT = 1 ,
@userId INT = 5,
@bookId INT = 1
DECLARE @BucketId INT = 0
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @PlanningSeason NVARCHAR(20)
DECLARE @StructureId INT = 9
DECLARE @AllocStructureId INT = 11
DECLARE @UpdatedUser INT = 2
DECLARE @InsertOne NVARCHAR(MAX) =''
DECLARE @AreaSchema NVARCHAR(40)
DECLARE @AreaCode NVARCHAR(20)
DECLARE @EmptyValue NVARCHAR(20)
SET @AreaCode = ''
SET @AreaSchema = '[dbo]'
SET @InsertOne =
'DECLARE @FGSupplySeqId INT = 5
DECLARE @FGSupplyId NVARCHAR(10) = ''''
DECLARE @PlannedQty DECIMAL(18,2) = ''''
DECLARE @ConfirmdQty DECIMAL(18,2) = ''''
DECLARE @Year INT = 2015
DECLARE @Month INT = 7
DECLARE @Season NVARCHAR(20) = ''''
DECLARE @MerchantId NVARCHAR(50) = ''''
DECLARE @UpdatedUser INT
DECLARE @HierarchyId NVARCHAR(10) = ''''
DECLARE @BucketId INT = 0
DECLARE @ProductNo NVARCHAR(100)= ''''
DECLARE @LocationNo NVARCHAR(100)
SET @BucketId = '+ CAST(@BucketId AS VARCHAR) + '
SET @UpdatedUser = '+ CAST(@userId AS VARCHAR) + '
IF @BucketId = 1
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ '
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year,Season,ProductNo,LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId NVARCHAR(10)
DECLARE @AllocStatus INT
SET @FGAllocationId = ''E''
SET @AllocStatus= 0
SELECT @FGAllocationId = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] IS NULL
IF @FGAllocationId = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FinishedGoodSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END
IF @BucketId = 2
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ 'AND Month IS NOT NULL
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year, Month,Season,@ProductNo,@LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId AND Month IS NOT NULL
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId1 NVARCHAR(10)
SET @FGAllocationId1 = ''E''
SELECT @FGAllocationId1 = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] = @Month
IF @FGAllocationId1 = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Month,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Month,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId1
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END'
print @InsertOne
我正在使用 NVARCHAR(MAX)
创建动态 query.Since NVARCHAR
每个字符使用 2 个字节,NVARCHAR(MAX)
变量中可以包含大约 10 亿个字符 (Link Reference).
我尝试在 SQL 服务器本身中执行存储过程,然后通过应用程序执行存储过程。
这两种情况动态查询都是不超过那些字符长度的。但只有部分动态查询是获取 executed.Because 存储过程向应用程序抛出错误。
我是否遗漏了任何代码?
USE [MyDemoDB]
GO
ALTER PROCEDURE [dbo].[sp_Apply]
(
@scenarioId INT,
@userId INT,
@bookId INT
)
AS
DECLARE @BucketId INT
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @PlanningSeason NVARCHAR(20)
DECLARE @StructureId INT = 9
DECLARE @AllocStructureId INT = 11
DECLARE @UpdatedUser INT = 2
DECLARE @InsertOne NVARCHAR(MAX)=''
DECLARE @AreaSchema NVARCHAR(40)
DECLARE @AreaCode NVARCHAR(20)
DECLARE @EmptyValue NVARCHAR(20)
SET @AreaCode = ''
SET @AreaSchema = '[dbo]'
SET @InsertOne = '
DECLARE @FGSupplySeqId INT
DECLARE @FGSupplyId NVARCHAR(10)
DECLARE @PlannedQty DECIMAL(18,2)
DECLARE @ConfirmdQty DECIMAL(18,2)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @Season NVARCHAR(20)
DECLARE @MerchantId NVARCHAR(50)
DECLARE @UpdatedUser INT
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @BucketId INT
DECLARE @ProductNo NVARCHAR(100)
DECLARE @LocationNo NVARCHAR(100)
SET @BucketId = '+ CAST(@BucketId AS VARCHAR) + '
SET @UpdatedUser = '+ CAST(@userId AS VARCHAR) + '
IF @BucketId = 1
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ '
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year,Season,ProductNo,LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId NVARCHAR(10)
DECLARE @AllocStatus INT
SET @FGAllocationId = ''E''
SET @AllocStatus= 0
SELECT @FGAllocationId = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] IS NULL
IF @FGAllocationId = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FinishedGoodSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END
IF @BucketId = 2
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ 'AND Month IS NOT NULL
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year, Month,Season,@ProductNo,@LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId AND Month IS NOT NULL
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId1 NVARCHAR(10)
SET @FGAllocationId1 = ''E''
SELECT @FGAllocationId1 = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] = @Month
IF @FGAllocationId1 = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Month,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Month,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId1
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END'
print @InsertOne
EXEC(@InsertOne)
确保您的变量不包含引号或双引号。
declare @value nvarchar(100) = 'abcd''efgh' declare @sql nvarchar(max) -- tons of QUOTE !!! Set @sql = N'select ''' + REPLACE(@value, '''', '''''') + ''''; print @sql exec sp_executesql @sql
将您的对象名称用括号括起来,并在 into 和 DB:
之间至少加上一个 spaceINSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation] -- space is missing
或者您可以使用 QUOTENAME 函数
QUOTENAME(@AreaSchema)
使用 N'' 和 NVARCHAR(...) 或 '' 和 VARCHAR() 但不要混用
您将所有内容声明为 NVARCHAR,然后将其与 '' 连接。应该是N''。您还将 convert/cast 一切都作为 VARCHAR。它应该是 NVARCHAR(...)。 动态 SQL 使用 NVARCHAR 字符串。
确保变量已设置或具有默认值
SET @BucketId = '+ CAST(@BucketId AS nVARCHAR) + '
这将 return NULL,因为@BucketId 未在您的存储过程中设置。使用 ISNULL,设置它或给它一个默认值
您应该使用 EXEC sp_executesql 并在使用时声明变量 https://msdn.microsoft.com/fr-fr/library/ms188001(v=sql.120).aspx
EXEC sp_executesql @yourquery, N'@UserID int, ...', @userID = @UserId ...
仅在需要时保持串联(动态对象名称)
- 终于
在尝试执行它之前,请确保您的打印输出正确的查询(打印仅显示前 4000 个字符)。如果查询不完整,可能意味着您在停止处附近的代码中有错误。 我试过你的过程,但它 return 没有任何东西(NULL),除非我首先初始化所有变量。还有截断,因为你不使用 N''
是的,您可能遇到了这个问题,因为 nvarchar 的限制是 4000 个字符。
我也遇到这个问题,通过连接字符串然后执行来解决。
如果您 select 或打印它只显示 4000 个字符,但如果您连接或追加字符串,它必须追加(直到 8000 个字符)。所以不要为此烦恼,你不打印或 select 只是追加和执行它绝对有效。
在此
declare @sql Nvarchar(max),
@a nvarchar(max),
@b nvarchar(max);
select @sql =N'', @a = N'a', @b = N'b';
select @sql = @sql +replicate(@a,4000) + replicate(@b, 6000);
select len(@sql)
为此有 one rule :-
SET @dynamicSQL = [concatenate various unicode strings and nvarchar variables totalling over 4000 characters] -- MAKE SURE AT LEAST ONE OF THE UNICODE STRINGS IS NVARCHAR(MAX), YOU CAN CAST ANY ONE ARGUMENT.
你也可以检查这个link。
已更新 我展示了你的整个代码,并想解释一些事情。
首先,为什么要动态查询。代码显示你可以在没有动态查询的情况下做到这一点,而且还有很多嵌套游标(尝试通过简单查询忽略它)
不过,如果你想去,那么我会删除你额外的代码(我不认为删除 space 会起作用,我有 4 个联合查询,它的长度非常大,它在单独验证每个部分后使用此策略 window)
a.Here 是另一种选择。除了在查询中定义参数,您也可以传递此参数。
begin tran
create table table1 ( id int, value varchar(10) )
insert into table1 values( 1,'001')
insert into table1 values(2, '002')
insert into table1 values( 3,'003')
insert into table1 values( 4,'004')
declare @sql nvarchar(max) , @temp nvarchar(50) = '1,2,3', @tempIntSingleValue nvarchar(50) = '2'
select * from table1
set @sql = 'select * from table1 where id in ( ' + @temp + ')'
print @sql
exec sp_executesql @sql
set @sql = 'select * from table1 where id in ( @tempInner)'
print @sql
exec sp_executesql @sql , N'@tempInner int', @tempInner = @tempIntSingleValue
rollback
b。您在动态查询中使用了相同的参数。所以我认为你必须给出默认值或在 运行 时间分配值。所以在连接你的字符串时不会变成空。请参阅下面的示例。我将所有字符定义为 '' 并将 int 定义为数值,最后 print 打印一些东西。如果我们不定义它永远不会打印空白,因为连接设置了空值。
declare @scenarioId INT = 1 ,
@userId INT = 5,
@bookId INT = 1
DECLARE @BucketId INT = 0
DECLARE @HierarchyId NVARCHAR(10)
DECLARE @Year INT
DECLARE @Month INT
DECLARE @PlanningSeason NVARCHAR(20)
DECLARE @StructureId INT = 9
DECLARE @AllocStructureId INT = 11
DECLARE @UpdatedUser INT = 2
DECLARE @InsertOne NVARCHAR(MAX) =''
DECLARE @AreaSchema NVARCHAR(40)
DECLARE @AreaCode NVARCHAR(20)
DECLARE @EmptyValue NVARCHAR(20)
SET @AreaCode = ''
SET @AreaSchema = '[dbo]'
SET @InsertOne =
'DECLARE @FGSupplySeqId INT = 5
DECLARE @FGSupplyId NVARCHAR(10) = ''''
DECLARE @PlannedQty DECIMAL(18,2) = ''''
DECLARE @ConfirmdQty DECIMAL(18,2) = ''''
DECLARE @Year INT = 2015
DECLARE @Month INT = 7
DECLARE @Season NVARCHAR(20) = ''''
DECLARE @MerchantId NVARCHAR(50) = ''''
DECLARE @UpdatedUser INT
DECLARE @HierarchyId NVARCHAR(10) = ''''
DECLARE @BucketId INT = 0
DECLARE @ProductNo NVARCHAR(100)= ''''
DECLARE @LocationNo NVARCHAR(100)
SET @BucketId = '+ CAST(@BucketId AS VARCHAR) + '
SET @UpdatedUser = '+ CAST(@userId AS VARCHAR) + '
IF @BucketId = 1
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ '
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year,Season,ProductNo,LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId NVARCHAR(10)
DECLARE @AllocStatus INT
SET @FGAllocationId = ''E''
SET @AllocStatus= 0
SELECT @FGAllocationId = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] IS NULL
IF @FGAllocationId = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FinishedGoodSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END
IF @BucketId = 2
BEGIN
DECLARE Supplys
CURSOR FOR
SELECT [FGSupplySeqId],[FGSupplyId] FROM ' + @AreaSchema + '.[FGSupply]
WHERE PlanningScenarioId ='+ CONVERT(VARCHAR(10),@scenarioId)+ 'AND Month IS NOT NULL
OPEN Supplys
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE Allocations
CURSOR FOR
SELECT @FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,ConfirmedQty,Year, Month,Season,@ProductNo,@LocationNo
FROM '+ @AreaSchema +'.[FGAllocation]
WHERE FGSupplySeqId = @FGSupplySeqId AND Month IS NOT NULL
OPEN Allocations
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FGAllocationId1 NVARCHAR(10)
SET @FGAllocationId1 = ''E''
SELECT @FGAllocationId1 = FGAllocationId,@AllocStatus=Status
FROM ' + @AreaSchema+'.[SN_PLANNING_FGAllocation]
WHERE [HierarchyId]=@HierarchyId AND [MerchantNo]=@MerchantId AND YEAR = @Year AND [Month] = @Month
IF @FGAllocationId1 = ''E''
BEGIN
-- IF @AllocStatus <> 5
INSERT INTO'+ @AreaSchema+'.[SN_PLANNING_FGAllocation]
(FGSupplyId,FGHierarchyId,MerchantNo,PlannedQty,Year,Month,Season,Status,IsActive,CreatedBy,UpdatedBy,CreatedOn,UpdatedOn,ProductNo,LocationNo)
VALUES(@FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@Year,@Month,@Season,0,1,@UpdatedUser,@UpdatedUser,GETDATE(),GETDATE(),@ProductNo,@LocationNo)
END
ELSE
BEGIN
-- IF @AllocStatus <> 5
UPDATE ' + @AreaSchema + '.[SN_PLANNING_FGAllocation]
SET PlannedQty = @PlannedQty ,ConfirmedQty=@ConfirmdQty,UpdatedBy=@UpdatedUser, UpdatedOn=GETDATE()
WHERE FGAllocationId = @FGAllocationId1
END
FETCH NEXT
FROM Allocations
INTO @FGSupplyId,@HierarchyId,@MerchantId,@PlannedQty,@ConfirmdQty,@Year,@Month,@Season,@ProductNo,@LocationNo
END
CLOSE Allocations
DEALLOCATE Allocations
FETCH NEXT
FROM Supplys
INTO @FGSupplySeqId,@FGSupplyId
END
CLOSE Supplys
DEALLOCATE Supplys
END'
print @InsertOne