2009-09-04 165 views
0

如果我有这个存储过程定义减去身体TSQL存储过程的参数错误

ALTER PROCEDURE sp_AlloctionReport(@where NVARCHAR(1000), @alldate NVARCHAR(200), @alldateprevweek NVARCHAR(200)) 
AS 

我呼吁这个样子。

sp_AllocationReport "ProductCode = 'FA' AND AllocationDate = '20090112' AND VenueInfo.VenueID In(SELECT vf.VenueID FROM VenueFilters vf INNER JOIN FilterTypes ft ON vf.FilterTypeID = ft.FilterTypeID WHERE ft.FilterDescription = 'Coke') AND State = 'NSW'","CampaignAllocations.AllocationDate = '20090112'","CampaignAllocations.AllocationDate = '20090105'" 

当我的第一个参数定义为NVARCHAR(1000)时,为什么会出现此错误。

以 '的ProductCode = 'FA' AND AllocationDate = '20090112' AND VenueInfo.VenueID IN(SELECT vf.VenueID FROM VenueFilters VF INNER JOIN网络连接' 太长。最大长度是开始标识符128

回答

1
  1. 以where子句,并在一个新的文件
  2. '与 '替换' 编辑(单引号 - >双单引号)
  3. EXEC dbo.sp_AllocationReport @where= '<THE TEXT EDITED ABOVE>'
0
  • 检查双引号“可乐”。语法highligher使误差明显。
  • 使用单引号主弦,和双逃脱他们需要的地方。是的,这是一个痛苦,但它是正确的方式做它
  • 前缀NVarchar文字与大写N
  • 这是一个SQL注入攻击等待发生的气味。你确定你需要作为字符串变量传递SQL吗?
+0

我试过用单引号,但给出了相同的错误。这是一个Access前端应用程序内部,所以它可以使用字符串。 – Malcolm 2009-09-04 03:51:02

+0

没错。没关系,因为内部员工从不做坏事。祝你好运。 – 2009-09-04 12:16:46

0

的最大长度一个对象在SQL服务器128字符(我认为)。在编译查询时,可能是一个语法问题,它认为整个字符串是一个表/视图名称?

0

如果我们有存储过程的主体,它可能会更清晰。但是......看起来像是SQL Server将您的参数解释为一个indentifer(即列名称)。线索是错误信息,其中指出“以'ProductCode ='FA'AND [...]开头的标识符太长”。即,SQL Server正在寻找一个命名为“产品代码=‘FA’和[...等等...]

所以我怀疑是你的存储过程中做到了这:

SELECT col1, col2, col3, ... FROM table WHERE @where 

...和你希望where子句工作就像那样。

假设这是你所做的,它将无法工作。如果这不是你所做的,这个答案的其余部分可能完全是假的:-)如果你可以给出一个sproc主体的例子,它可能会让事情变得更加清晰。

因此,假如我suspision是正确的,你需要把它写成一个动态SQL语句是这样的:

DECLARE @sql NVARCHAR(2000) 
SET @sql = 'SELECT col1, col2, col3, ... FROM table WHERE ' + @where 
EXEC sp_ExecuteSQL @sql 

无论其 ......即使这不是故事的结尾这很容易发生注入攻击,这是a very bad thing。你最好做的是改变params到你存储的proc中,以利用参数化的SQL,这不会容易发生注入攻击。像这样...

ALTER PROCEDURE sp_AllocationReport (@ProductCode VARCHAR(10), @AllocationDate DATETIME, {rest of your parameters}) 
AS 
    DECLARE @sql NVARCHAR(2000) 
    SET @sql = 'SELECT col1, col2, col3, ... FROM table WHERE 1 = 1' 

    IF ISNULL(@ProductCode, '') <> '' 
     SET @sql = @sql + ' AND ProductCode = @pProductCode' 
    IF @AllocationDate IS NOT NULL 
     SET @sql = @sql + ' AND AllocationDate = @pAllocationDate' 
    {other conditionals, depending on what you need to pass in} 

    EXEC sp_ExecuteSQL @sql, '@pProductCode VARCHAR(10), 
           @pAllocationDate DATETIME, 
           {other passed in params} 
          ', @ProductCode, @AllocationDate 

此代码不容易发生注入式攻击。由于SQL Server会更可靠地缓存执行计划,因此它也更具性能。了解这一点;这里有很多。