TSQL存储的proc参数错误

时间:2009-09-04 03:40:29

标签: sql sql-server 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'开头的标识符和AllocationDate ='20090112'和VenueInfo.VenueID In(SELECT vf.VenueID FROM VenueFilters vf INNER JOIN Fi'太长。最大长度为128.

5 个答案:

答案 0 :(得分:1)

  1. 获取where子句并在新文件中编辑
  2. 将'替换为''(单引号 - >双单引号)
  3. EXEC dbo.sp_AllocationReport @where= '<THE TEXT EDITED ABOVE>'

答案 1 :(得分:0)

  • 检查“可乐”周围的双引号。语法highligher使错误显而易见。
  • 对主字符串使用单引号,并在需要时双重转义它们。是的,这是一种痛苦,但这是正确的做法。
  • 使用大写N
  • 作为前缀的NVarchar文字
  • 这种sql注入黑客的气味等待发生。你确定需要将sql作为字符串变量传递吗?

答案 2 :(得分:0)

sql server中对象的最大长度为128个字符(我认为)。构建查询时,语法问题可能使整个字符串成为表/视图名称?

答案 3 :(得分:0)

除非连接QUOTED_IDENTIFIER已打开,否则必须使用单引号而不是双引号

http://msdn.microsoft.com/en-us/library/ms174393.aspx

这是SQL 2000以后的默认设置,但如果您从旧版本升级,则旧默认设置仍然有效。

答案 4 :(得分:0)

如果我们有存储过程的主体,它可能会更清楚。但是......它看起来是SQL Server将您的参数解释为一个不明确的(即列名)。线索是错误消息,其中指出“ 以'ProductCode ='FA'和[...]开头的标识符太长” 。即,SQL Server正在寻找名为“ ProductCode ='FA'和[... etc ...] ”的

所以我怀疑你是在存储过程中完成的:

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

...并希望where子句能够像那样工作。

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

因此,假设我的怀疑是正确的,您需要将其写为动态SQL语句,如下所示:

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

HOWEVER ...即使这不是故事的结尾,因为这很容易发生注射攻击,a very bad thing。你最好做的是将params改为你的存储过程,以利用参数化的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可以更可靠地缓存执行计划,因此性能也更高。阅读这个;那里有很多东西。