MSSQL参数化查询导致“关键字附近的语法不正确”来自'“

时间:2013-01-25 20:37:56

标签: sql-server

我有一个参数化查询,如下所示:

SELECT title, html, shortname FROM dbo.Videos
WHERE Topic_ID = ? AND dbo.gradeLevelCheck(?, Grade_Lower, Grade_Upper) = 1
ORDER BY shortname ASC

当我从ASP运行它时,出现错误信息:

Incorrect syntax near the keyword 'from'

参数是561(因此没有空值)。存储的函数dbo.gradeLevelCheck如下所示:

ALTER FUNCTION [dbo].[gradeLevelCheck]
(
    @value int,
    @lower int,
    @upper int
)
RETURNS int
AS
BEGIN
    DECLARE @result int;
    IF (@lower IS NULL OR @lower <= @value) AND (@upper IS NULL OR @upper >= @value)
        SET @result = 1;
    ELSE
        SET @result = 0;
    RETURN @result;
END

如果我使用硬编码到查询中的参数提交它,它可以正常工作。如果我删除ORDER BY子句,它也可以正常工作。但我不能让它以这种形式工作。任何人都可以帮我找出原因吗?

编辑:这是一些额外的细节。该应用程序是使用JScript在Classic ASP中编写的。因此建立了连接:

        var conn = Server.CreateObject('ADODB.Connection');
        var connectionString =
            'Provider=SQLOLEDB;' +
            'Data Source=' + Settings.dbServer + ';' +
            'Initial Catalog=' + Settings.dbCatalog + ';' +
            'User Id=' + Settings.dbUser + ';' +
            'Password=' + Settings.dbPass + ';' +
            'Connect Timeout=15;';
        conn.Open(connectionString, conn);

用于提交查询的代码如下所示:

    DB.query = function(query) {
    ...
            var cmd = Server.CreateObject("ADODB.Command");
            cmd.activeConnection = conn;
            cmd.commandText = query;
            for (var i = 1; i < arguments.length; i++) {
                cmd.Parameters(i-1).value = arguments[i];
            }
            return cmd.Execute();
    ...
    }

(此处,参数156作为DB.query的附加参数传递。)

3 个答案:

答案 0 :(得分:6)

“来自''的关键字附近的”语法不正确“是通过连接字符串并忘记单词之间的某些空格来构建查询时遇到的经典错误。我猜这里第一行的末尾(...视频)和第二行的开头(WHERE ......)之间缺少空格

答案 1 :(得分:2)

我看到了查询文本,我看到该函数是如何接受该文本的,但我仍然缺少一个准确诊断它的方法:如何将查询文本放入代码中?

我问,因为我觉得你有这样的事情:

query = "SELECT title, html, shortname FROM dbo.Videos"
      + "WHERE TopicID = ? .... ";

注意创建该字符串变量时会发生什么。它看起来像这样:

  

SELECT标题,html,短名称FROM dbo.VideosWHERE TopicID =? ....

请注意dbo.VideosWHERE之间根本没有任何内容。您没有在两行之间包含任何空格。原始代码中的换行符不是字符串文字的一部分。你需要这样的东西:

query = "SELECT title, html, shortname FROM dbo.Videos"
     + " WHERE TopicID = ? .... ";

请注意为WHERE关键字添加空格。


另一个建议是删除dbo.部分,只使用Videos作为表名。我知道你拥有的应该是有效的语法,但是必须要进行一些不寻常的事情或者我们已经解决了它。还有一件事要在表和列名称周围放置括号。

答案 2 :(得分:1)

我相信我已经找到了问题所在。这是我的假设:

通常ADO能够根据查询结构推断参数类型。但是,在这种情况下,预准备语句的一个参数是函数dbo.gradeLevelCheck的参数,这会导致类型推断失败。 (据推测,ADO不了解存储的函数或其他东西,所以它不知道如何检查参数应该是什么类型。)因为它无法弄清楚类型,所以查询无效。

我仍然不知道为什么在删除ORDER BY子句时此查询似乎有效,但显然我必须更改代码。