尝试使用TSql100Parser解析时无法正确解析sql脚本

时间:2013-04-23 10:39:46

标签: c# sql parsing

我正在使用ScriptDom来解析SQL脚本。我的程序如下

static void Main(string[] args)
        {
            string script = @"
                            SET QUOTED_IDENTIFIER ON
                            GO

                            SET ANSI_NULLS ON
                            GO

                            CREATE PROCEDURE dbo.ws_Device_Update
                            (
                                @ApplicationId uniqueidentifier   ,
                                @OriginalApplicationId uniqueidentifier   ,
                                @DeviceIMEI nvarchar (50)  ,
                                @OriginalDeviceIMEI nvarchar (50)  ,
                                @ModelId int   ,
                                @DeviceName nvarchar (50)  ,
                                @DeviceDescription nvarchar (255)  ,
                                @DeviceState int   ,
                                @IsExpired bit   ,
                                @IsSuspended bit   ,
                                @LastAccessed datetime   ,
                                @ClientSeqNo bigint   ,
                                @ServerSeqNo bigint   ,
                                @ModelCode varchar (50)  ,
                                @PushToken varchar (512)  ,
                                @PushLastAlive datetime   ,
                                @PushLastDead datetime   ,
                                @DeviceType int   
                            )

                            AS

                            UPDATE dbo.[ws_Device]
                            SET

                                 [ModelId]              = @ModelId           --Does a device model change with same DeviceIMEI .I doubt it
                                ,[DeviceName]           = @DeviceName        --Does a device name change with same DeviceIMEI .I doubt it
                                ,[DeviceDescription]    = @DeviceDescription --Does a device description change with same DeviceIMEI .I doubt it
                                ,[DeviceState]          = @DeviceState       
                                ,[IsExpired]            = @IsExpired
                                ,[IsSuspended]          = @IsSuspended
                                ,[LastAccessed]         = @LastAccessed
                                ,[ClientSeqNo]          = @ClientSeqNo
                                ,[ServerSeqNo]          = @ServerSeqNo
                                ,[ModelCode]            = @ModelCode         --Does a device model code with same DeviceIMEI .I doubt it
                                ,[PushToken]            = @PushToken
                                ,[PushLastAlive]        = @PushLastAlive
                                ,[PushLastDead]         = @PushLastDead
                                ,[DeviceType]           = @DeviceType        --Does a device device type change with same DeviceIMEI .I doubt it
                            WHERE
                                [ApplicationId]         = @OriginalApplicationId 
                            AND [DeviceIMEI]            = @OriginalDeviceIMEI
                            ";

            IList<ParseError> parseErrors;
            TSql100Parser tsqlParser = new TSql100Parser(false);
            TSqlFragment fragment;
            using (StringReader stringReader = new StringReader(script))
            {
                fragment = (TSqlFragment)tsqlParser.Parse(stringReader, out parseErrors);
            }
            if (parseErrors.Count > 0)
            {
                Console.WriteLine(@"Errors encountered: ""{0}""", parseErrors[0].Message);
            }

            Console.ReadKey();
        }

工作正常。

但如果我不提及

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

失败

遇到错误:“CREATE附近的语法不正确。”

我的问题是它发生的原因....如果没有 SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON ,它仍然是一个有效的存储过程。

OR是否必须使用它们?有没有办法绕过它?

2 个答案:

答案 0 :(得分:1)

Priyanka的问题是,在您的CREATE PROCEDURE文本之前有一个(不可见的)0xFFFE。如果使用键盘,可以验证这一点,转到C字符并将光标向左移动。你会发现在C的左边,光标似乎没有向左前进,除非你再次按下左箭头键。

0xFFFE是用于检测Unicode字节排序的字节顺序标记,我怀疑它已经以某种方式进入你的代码。现在,您只需使用DEL或BackSpace键删除隐藏的字符,它就可以修复它。

此外,将来总是将true传递给TSql100Parser类的构造函数。默认情况下,带引号的标识符处理为ON,因此我们需要在解析器构造函数中尊重它。

答案 1 :(得分:0)

阅读这两篇文章:
QUOT.ID:http://msdn.microsoft.com/en-us/library/ms188048.aspx
ANSI:http://msdn.microsoft.com/en-us/library/ms174393.aspx

在您的情况下,可能缺少后者导致问题,因为您的UPDATE获取NULL(s)