如何诊断和修复 "Error formatting query, probably invalid parameters, incorrect syntax" 错误?

How do I diagnose and fix "Error formatting query, probably invalid parameters, incorrect syntax" error?

我正在整理一个存储过程,该过程将一些查询结果作为 CSV 附件发送到电子邮件中。我正在测试程序并收到此错误:

Msg 22050, Level 16, State 1, Line 2 Error formatting query, probably invalid parameters Msg 14661, Level 16, State 1, Procedure sp_send_dbmail, Line 517 [Batch Start Line 2] Query execution failed: Msg 102, Level 15, State 1, Server NRWOGMSQL6ST\SQLSTD2012, Line 27 Incorrect syntax near 'tbl'.

我知道在 CSV 中生成结果的查询是有效的,因为我已经在 SP 之外对其进行了测试。我相信所有引用都是正确的,因为我打印了查询并仔细检查了转义引号。我尝试使用 @query_result_no_padding = 1 但它在附加的 CSV 中给了我同样的错误。我也知道 SP 的电子邮件部分有效,因为我一直在使用测试查询来测试事物(请参阅以“SELECT TOP 100”开头的注释掉的查询)。

我认为错误是指 tblAPDTracker table。我试着注释掉这一行,但下一个错误对“Well”table 说了同样的话。我无法注释掉 table 井,因为它是我使用的第一个 table。有什么方法可以获取有关问题所在以及我该如何解决的更多信息?

USE [UTRBDMSNET]
GO
/****** Object:  StoredProcedure [dbo].[TestProcedure] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[HiebingTestProcedure] 

AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @message VARCHAR(1000);
    DECLARE @subject VARCHAR(100);
    DECLARE @query VARCHAR(1000);
    DECLARE @tab char(1) = CHAR(9);
    DECLARE @query_attachment_filename VARCHAR(520);
    DECLARE @CRLF char(2);

    SELECT @CRLF = CHAR(13)+CHAR(10)
    SELECT @subject = 'Well Information Report'
    SELECT @message = N'Dear Zeke, '
                      +@CRLF+ ''
                      +@CRLF+ N'Please refer to the attached spread sheet for the results of last month''s information report.'
                      +@CRLF+ ''
                      +@CRLF+ 'Thanks,'
                      +@CRLF+ 'Matt';

    --SELECT @query = 
    --   'SET NOCOUNT ON;
    --    SELECT TOP 100 WellID, Operator, WellStatus, ModifyUser
    --    FROM UTRBDMSNET.dbo.Well';

    SELECT @query =
    '
        SET NOCOUNT ON;
        DECLARE @SearchYear AS VARCHAR(4) = 2020
        DECLARE @SearchMonth AS VARCHAR(2) = 7

        SELECT
            API14,
            [Entity Number],
            [First Prod Date],
            [Spacing Rule],
            TPI AS ''Top Producing Interval Location'',
            BH AS ''Bottom Hole Location'',
            [Well History Comments],
            [Well History Modify Date] AS ''Last Modified Date''
        FROM
        (
        SELECT
            dbo.BuildAPI14(Well.WellID, Construct.SideTrack, Construct.Completion) AS ''API14'',
            CAST(ConstructDate.EventDate AS DATE) AS ''First Prod Date'',
            Loc.LocType AS ''Location Type'',
            CONCAT(''Township '',LocExt.Township,LocExt.TownshipDir,'' '',''Range '',LocExt.Range,LocExt.RangeDir,'' Section '',LocExt.Sec,'' '',RefCounty.CountyName,'' County'') AS ''Location'',
            tblAPDTracker.SpacingRule AS ''Spacing Rule'',
            Lease.Number AS ''Entity Number'',
            WellHistory.WHComments AS ''Well History Comments'',
            WellHistory.ModifyDate AS ''Well History Modify Date''
        FROM UTRBDMSNET.dbo.Well
            LEFT JOIN UTRBDMSNET.dbo.tblAPDTracker ON LEFT(tblAPDTracker.APINO,10) = Well.WellID
            LEFT JOIN UTRBDMSNET.dbo.Construct ON Construct.WellKey = Well.PKey
            LEFT JOIN UTRBDMSNET.dbo.ConstructReservoir ON ConstructReservoir.ConstructKey = Construct.PKey
            LEFT JOIN UTRBDMSNET.dbo.Lease ON Lease.Pkey = ConstructReservoir.LeaseKey
            LEFT JOIN UTRBDMSNET.dbo.WellHistory ON WellHistory.WellKey = Construct.WellKey
            LEFT JOIN UTRBDMSNET.dbo.ConstructDate ON ConstructDate.ConstructKey = Construct.PKey AND ConstructDate.Event = ''FirstProduction''
            LEFT JOIN UTRBDMSNET.dbo.Loc ON loc.ConstructKey = Construct.PKey AND Loc.LocType IN (''BH'',''TPI'')
            LEFT JOIN UTRBDMSNET.dbo.LocExt ON LocExt.LocKey = Loc.PKey
            LEFT JOIN UTRBDMSNET.dbo.RefCounty ON RefCounty.PKey = LocExt.County
        WHERE
                WellHistory.WorkType = ''ENTITY''
            AND WellHistory.ModifyUser = ''UTAH\rachelmedina''
            AND YEAR(WellHistory.ModifyDate) = @SearchYear
            AND MONTH(WellHistory.ModifyDate) = @SearchMonth
        GROUP BY
            Well.WellID,
            Construct.SideTrack,
            Construct.Completion,
            ConstructDate.EventDate,
            Loc.LocType,
            LocExt.Township,
            LocExt.TownshipDir,
            LocExt.Range,
            LocExt.RangeDir,
            LocExt.Sec,
            RefCounty.CountyName,
            tblAPDTracker.SpacingRule,
            Lease.Number,
            WellHistory.WHComments,
            WellHistory.ModifyDate
        ) AS BasicQuery
        PIVOT
        (
        MIN(BasicQuery.Location) FOR [Location Type] IN ([TPI], [BH])
        ) AS PivotedQuery
        ORDER BY
            API14,
            [Well History Modify Date];
    '
    
    SELECT @query_attachment_filename = 'TestingEmailAttachment.csv';

    EXEC msdb.dbo.sp_send_dbmail
        @profile_name = 'OilGasEmail',
        @from_address = 'mhiebing@utah.gov',
        @recipients = 'mhiebing@utah.gov ',
        @body = @message,
        @query = @query,
        @query_attachment_filename = @query_attachment_filename,
        @attach_query_result_as_file = 1,
        @query_result_header = 1,
        @query_result_width = 32767,
        @query_result_separator = @tab,
        @append_query_error = 0
        --@query_result_no_padding = 1;
END

下面是我希望在电子邮件 CSV 中看到的几行结果。

API14 Entity Number First Prod Date Spacing Rule Top Producing Interval Location Bottom Hole Location Well History Comments Last Modified Date
43013534820000 100260 2019-01-09 139-134 Township 3S Range 1W Section 22 DUCHESNE County Township 3S Range 1W Section 15 DUCHESNE County Moved to CTB entity 100401 2020-07-15 17:27:00
43013534820000 100401 2019-01-09 139-134 Township 3S Range 1W Section 22 DUCHESNE County Township 3S Range 1W Section 15 DUCHESNE County Moved to CTB entity 100401 2020-07-15 17:27:00
43013534860000 100246 2019-01-09 139-134 Township 3S Range 1W Section 22 DUCHESNE County Township 3S Range 1W Section 15 DUCHESNE County Moved to CTB entity 100401. 2020-07-15 17:28:00

问题非常简单,以至于被忽略了:由于 @query 变量未声明为足够大的大小以容纳查询而导致的字符串截断。

@query 更改为 VARCHAR(4000) 即可,但 NVARCHAR(MAX) 是最佳/理想选择。

我开始将截断视为错误原因的原因是由于错误消息:

| 'tbl'.

附近的语法不正确

表面上看起来是一个 table 别名,但我搜索并发现字符串 tbl 仅用作 table 名称的前缀。当您收到一条只有部分文本的错误消息时,这通常表明优化器没有看到查询的其余部分(或者错误消息太长而被截断,但显然不是这种情况在这里)。

补充说明

此外,与我建议使用 NVARCHAR 而不是 VARCHAR 相关,看看代码中至少有一些字符串文字以 N 为前缀(使它们成为 NVARCHAR 文字):您应该将所有变量声明为 NVARCHAR,因为如果使用了不属于代码的任何字符,这样可以减少将来数据丢失的可能性与当前数据库的默认排序规则关联的页面(“当前”是此存储过程所在的位置)。同样,CHAR 变量应该是 NCHAR.

那么,所有的字符串文字都应该以N为前缀,而不仅仅是其中的一些。

最后,列名别名(即 AS 之后的别名)应该使用方括号而不是单引号。例如:

Loc.LocType AS [Location Type]

而不是:

Loc.LocType AS ''Location Type''