【问题标题】:SQL Server and sqsh Incorrect syntax near the keyword 'ORDER'SQL Server 和 sqsh 关键字“ORDER”附近的语法不正确
【发布时间】:2019-01-01 08:37:30
【问题描述】:

我正在使用sqsh来执行一个存储过程:

我简化了这样的程序,以便您阅读:

CREATE PROCEDURE MyProc
    
AS
BEGIN
            SELECT *
            FROM Keys
            WHERE 1=1
            ;WITH CTE AS
            (
                SELECT TOP 1 *
                FROM MyTableName
                ORDER BY CreationTime ASC
            )
            SELECT *
            FROM CTE
END
;
go

我得到的错误是这样的:

Use: \go [-d display] [-h] [-f] [-n] [-p] [-m mode] [-s sec]
          [-t [filter]] [-w width] [-x [xgeom]] [-T title] [xacts]
     -d display  When used with -x, send result to named display
     -h          Suppress headers
     -f          Suppress footers
     -n          Do not expand variables
     -p          Report runtime statistics
     -m mode     Switch display mode for result set
     -s sec      Sleep sec seconds between transactions
     -t [filter] Filter SQL through program
                 Optional filter value overrides default variable $filter_prog
     -w width    Override value of $width
     -x [xgeom]  Send result set to a XWin output window
                 Optional xgeom value overrides default variable $xgeom
     -T title    Used in conjunction with -x to set window title
     xacts       Repeat batch xacts times
Msg 156, Level 15, State 1
Server 'myServer', Procedure 'MyProc', Line xx
Incorrect syntax near the keyword 'ORDER'.

这是未简化的版本:

CREATE PROCEDURE [dbo].[MyCustomProcedure]
    @BatchSize INT  WITH ENCRYPTION
AS
BEGIN
            DECLARE @CurrentName varchar(max)
            SET @CurrentName = [dbo].[GetCurrentyName]()
            DECLARE @CurrentID INT
            SELECT @CurrentID=ID FROM [dbo].[Keys] WHERE OriginalName = @CurrentName

            ;WITH CTE AS
            (
                SELECT TOP (@BatchSize) *
                FROM [dbo].[SerialNumbers]
                WHERE ID <> @CurrentID
                ORDER BY CreationTime ASC
            )
            UPDATE CTE
                SET EncodedSerial = (Encode(Key_GUID(@CurrentName), CONVERT(VARCHAR,(Decode(EncodedSerial))))),
                ID=@CurrentID
END
;

go

我已经看过其他类似的问题。 我找不到语法有什么问题,还能是什么? SQLServer 版本?

【问题讨论】:

  • 您的实际表名 (MyTable) 是 SQL Server 保留字吗?同样,如果直接在 SQL Server 中运行该过程,是否会出现错误?
  • 不,MyTable 不是实际的表名。为了清楚起见,我更改了它不幸的是现在我无法直接在 SQL Server 中尝试
  • 你已经简化了很多,你已经删除了错误。您发布的内容非常好。也许您应该分享实际代码?
  • 反正我一开始觉得CTE的更新很奇怪。但这个技巧毕竟有效。 simple test here
  • decode() ???您确定您使用的是 SQL Server?

标签: sql sql-server sql-server-2008 sqsh


【解决方案1】:

显然这已经很老了,但如果将来有人发现它,这里就是解决方案。

sqsh 使用命令\go 来拆分批次。 sqsh 还使用分号本身作为“关键字”作为一种内联\go 命令。所以本质上,你的程序被分成 2 个无意义的批次:

CREATE PROCEDURE [dbo].[MyCustomProcedure]
    @BatchSize INT  WITH ENCRYPTION
AS
BEGIN
            DECLARE @CurrentName varchar(max)
            SET @CurrentName = [dbo].[GetCurrentyName]()
            DECLARE @CurrentID INT
            SELECT @CurrentID=ID FROM [dbo].[Keys] WHERE OriginalName = @CurrentName

WITH CTE AS
            (
                SELECT TOP (@BatchSize) *
                FROM [dbo].[SerialNumbers]
                WHERE ID <> @CurrentID
                ORDER BY CreationTime ASC
            )
            UPDATE CTE
                SET EncodedSerial = (Encode(Key_GUID(@CurrentName), CONVERT(VARCHAR,(Decode(EncodedSerial))))),
                ID=@CurrentID
END

很遗憾,如果你删除分号,SQL Server 会报错,所以你需要禁用分号批量分隔功能。

来自手册页:

semicolon_hack (boolean)
           Toggles on the ability to use a ';' as an in-line command terminator. This feature is
           not recommended and is only in here because enough users complained.  See section
           COMMANDS, In-Line Go.

这是一个变量,您可以从 sqsh shell 或原始 sqsh 命令通过 -L 选项设置变量:-Lsemicolon_hack=false

您实际上有第二个错误,抱怨GO 的使用。如果您使用GOsqsh 将抛出错误。您将需要以任何一种方式提交批处理,否则 sqsh 将不会执行任何操作,因此将 GO 更改为 \go。所以最终的sql文件应该是这样的:

CREATE PROCEDURE [dbo].[MyCustomProcedure]
    @BatchSize INT  WITH ENCRYPTION
AS
BEGIN
            DECLARE @CurrentName varchar(max)
            SET @CurrentName = [dbo].[GetCurrentyName]()
            DECLARE @CurrentID INT
            SELECT @CurrentID=ID FROM [dbo].[Keys] WHERE OriginalName = @CurrentName

            ;WITH CTE AS
            (
                SELECT TOP (@BatchSize) *
                FROM [dbo].[SerialNumbers]
                WHERE ID <> @CurrentID
                ORDER BY CreationTime ASC
            )
            UPDATE CTE
                SET EncodedSerial = (Encode(Key_GUID(@CurrentName), CONVERT(VARCHAR,(Decode(EncodedSerial))))),
                ID=@CurrentID
END

\go

注意:您已经这样做了,但\go 命令必须始终以新行开头。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-18
    • 2013-12-04
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多