【问题标题】:sp_executeSQL errors in T-SQLT-SQL 中的 sp_executeSQL 错误
【发布时间】:2016-03-02 21:16:31
【问题描述】:

我正在尝试在 SQL Server 中编写一个 SP,它接受 4 个输入参数并返回查​​询结果,该查询将具有基于参数的 WHERE 语句。我正在尝试为此使用 sp_executeSql 但不断收到以下错误:

消息 102,第 15 级,状态 1,第 61 行 ')' 附近的语法不正确。 消息 137,第 15 级,状态 2,第 61 行 必须声明标量变量“@p_txnStDate”。

我找不到语法有任何问题(ALTER PROCEDURE 语句执行没有问题)并且明确声明了有问题的变量:

ALTER PROCEDURE [dbo].[usp_adm_rpt_autoBarStatusUpdates] 
    @p_reportType VARCHAR(50),
    @p_attyFName NVARCHAR(20),
    @p_attyLName NVARCHAR(254), 
    @p_txnStDate NVARCHAR(10),
    @p_txnFnDate NVARCHAR(10)
AS
BEGIN
    SET NOCOUNT ON;

    -- VARIABLE DECLARATION
    DECLARE @mainQuery AS NVARCHAR(2000)
    DECLARE @whereClause AS VARCHAR(300) 
    DECLARE @paramList AS NVARCHAR(50) 
    DECLARE @attyFName AS NVARCHAR(20)
    DECLARE @attyLName AS NVARCHAR(254)

    SET @whereClause = '' 
    SET @attyFName = UPPER(RTRIM(LTRIM(@p_attyFName)))
    SET @attyLName = UPPER(RTRIM(LTRIM(@p_attyLName)))

-- Dynamically construct the WHERE clause

-- First Name Paramater 
IF (LEN(ISNULL(RTRIM(LTRIM(@p_attyFName)),'')) > 0) 
    SET @whereClause = N'(UPPER(attyinfo.firstname) = @attyFName)'

-- Last Name Paramater 
IF (LEN(ISNULL(RTRIM(LTRIM(@p_attyLName)),'')) > 0)  
BEGIN
    IF (LEN(@whereClause) > 0) 
        SET @whereClause = @whereClause + N' AND (UPPER(attyinfo.lastname) = @attyLName)'
    ELSE
        SET @whereClause = N'(UPPER(attyinfo.lastname) = @attyLName)'
END

-- Dates - Between
IF ((LEN(@p_txnStDate) > 0) AND (LEN(@p_txnFnDate) > 0))
    BEGIN
        IF (LEN(@whereClause) > 0) 
            SET @whereClause = @whereClause + N' AND (status_chg_dt BETWEEN @p_txnStDate AND @p_txnFnDate)'
        ELSE
            SET @whereClause = N'(status_chg_dt BETWEEN @p_txnStDate AND @p_txnFnDate)'
    END
ELSE
    -- Start Date Only
    BEGIN
        IF (LEN(@p_txnStDate) > 0) 
            IF (LEN(@whereClause) > 0) 
                SET @whereClause = @whereClause + N' AND (status_chg_dt >= @p_txnStDate)'
            ELSE
                SET @whereClause = N'(status_chg_dt >= @p_txnStDate)'
    -- Finish Date Only
        ELSE IF (LEN(@p_txnFnDate) > 0) 
            IF (LEN(@whereClause) > 0) 
                SET @whereClause = @whereClause + N' AND (status_chg_dt <= @p_txnFnDate)'
            ELSE SET @whereClause = N'(status_chg_dt <= @p_txnFnDate)'
    END
END

-- Main query without the WHERE clause
SET @mainQuery = 'SELECT attyinfo.prid, attyinfo.personid, attyBarAutoStatusChanges.bm_id, attyBarAutoStatusChanges.pe_id, attyBarAutoStatusChanges.pr_id, CASE LEN(ISNULL(attyinfo.middlename,'''')) WHEN 0 THEN ISNULL(attyinfo.firstname,'''') + '' '' + ISNULL(attyinfo.lastname,'''') ELSE attyinfo.firstname + '' '' + attyinfo.middlename + '' '' + attyinfo.lastname END AS filed_by_atty, attyBarAutoStatusChanges.atty_3293_filed_for AS filed_for_atty, attyBarAutoStatusChanges.case_3293_filed_for AS filed_for_case, attyBarAutoStatusChanges.ltst_3293_filed_dt As filed_date, attyBarAutoStatusChanges.status_chg_dt, attyBarStatusBase.bar_status_init FROM attyinfo INNER JOIN attyBarAutoStatusChanges ON attyinfo.prid = attyBarAutoStatusChanges.pr_id AND attyinfo.personid = attyBarAutoStatusChanges.pe_id INNER JOIN attyBarStatusBase ON attyBarAutoStatusChanges.bm_id = attyBarStatusBase.bm_id AND attyBarAutoStatusChanges.pe_id = attyBarStatusBase.pe_id AND attyBarAutoStatusChanges.pr_id = attyBarStatusBase.pr_id WHERE attyBarAutoStatusChanges.op_code = ''BAR_STAT_AOR_TO_ACTV'''

-- Append WHERE clause (if applicable)
IF (LEN(@whereClause) > 0) 
    SET @mainQuery = @mainQuery + ' AND ' + @whereClause

-- Parameter List
SET @paramList = '@attyFName NVARCHAR, @attyLName NVARCHAR, @txnStDate NVARCHAR, @txnFnDate NVARCHAR'

-- Final Execution
EXEC sp_executesql @mainQuery, @paramList, @attyFName, @attyLName, @p_txnStDate, @p_txnFnDate

我不知道为什么这个程序会失败。我只需发出以下命令即可运行它:

EXEC usp_adm_rpt_autoBarStatusUpdates 'BAR_STAT_AOR_TO_ACTV', 'John', 'Joseph', '1/1/2016', '2/1/2016'

【问题讨论】:

  • **DECLARE @txnStDate...** 是怎么回事?这不是有效的语法,这就是您收到错误的原因。如果您想评论它,请使用/*...*/,但看到您实际上在代码中使用@txnStDate,您应该删除**
  • 仅供参考:IF ((LEN(@txnStDate) &gt; 0) AND (LEN(@txnStDate) &gt; 0)) 检查同一个变量两次,然后使用不同的变量 (@txnFnDate)。
  • @HABO - 很棒的收获!它应该是: ((LEN(@txnStDate) > 0) AND (LEN(@txnFnDate) > 0))
  • 在执行之前执行 PRINT @mainQuery。
  • PRINT 给出以下 WHERE 子句:WHERE attyBarAutoStatusChanges.op_code = 'BAR_STAT_AOR_TO_ACTV' AND (UPPER(attyinfo.firstname) = @attyFName) AND (UPPER(attyinfo.lastname) = @attyLName)与(@p_txnStDate 与@p_txnFnDate 之间的status_chg_dt)

标签: sql-server tsql stored-procedures


【解决方案1】:

为什么是 sp_executesql 而不是直接 SELECT?

试试这样的

ALTER PROCEDURE [dbo].[usp_adm_rpt_autoBarStatusUpdates] 
    @p_reportType VARCHAR(50),
    @p_attyFName NVARCHAR(20) = NULL,
    @p_attyLName NVARCHAR(254) = NULL, 
    @p_txnStDate NVARCHAR(10) = NULL,
    @p_txnFnDate NVARCHAR(10) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET DATEFORMAT dmy;

    DECLARE @attyFName AS NVARCHAR(20) = UPPER(RTRIM(LTRIM(@p_attyFName)))
    DECLARE @attyLName AS NVARCHAR(254) = UPPER(RTRIM(LTRIM(@p_attyLName))) 
    DECLARE @txnStDate DATE = @p_txnStDate
    DECLARE @txnFnDate DATE = @p_txnFnDate

    SELECT      attyinfo.prid,
                attyinfo.personid,
                attyBarAutoStatusChanges.bm_id,
                attyBarAutoStatusChanges.pe_id,
                attyBarAutoStatusChanges.pr_id,
                CASE LEN(ISNULL(attyinfo.middlename,''''))
                WHEN 0 THEN ISNULL(attyinfo.firstname,'''') + '' '' + ISNULL(attyinfo.lastname,'''')
                ELSE attyinfo.firstname + '' '' + attyinfo.middlename + '' '' + attyinfo.lastname
                END AS filed_by_atty,
                attyBarAutoStatusChanges.atty_3293_filed_for AS filed_for_atty,
                attyBarAutoStatusChanges.case_3293_filed_for AS filed_for_case,
                attyBarAutoStatusChanges.ltst_3293_filed_dt As filed_date,
                attyBarAutoStatusChanges.status_chg_dt,
                attyBarStatusBase.bar_status_init
    FROM        attyinfo
    INNER JOIN  attyBarAutoStatusChanges
    ON          attyinfo.prid = attyBarAutoStatusChanges.pr_id
    AND         attyinfo.personid =     attyBarAutoStatusChanges.pe_id
    INNER JOIN  attyBarStatusBase
    ON          attyBarAutoStatusChanges.bm_id = attyBarStatusBase.bm_id
    AND         attyBarAutoStatusChanges.pe_id = attyBarStatusBase.pe_id
    AND         attyBarAutoStatusChanges.pr_id = attyBarStatusBase.pr_id
    WHERE       attyBarAutoStatusChanges.op_code = 'BAR_STAT_AOR_TO_ACTV'

    AND         (
                (
                UPPER(attyinfo.firstname) = @attyFName
    AND         @attyFName IS NOT NULL
    AND         @attyFName <> ''
                )
    OR          @attyFName IS NULL
    OR          @attyFName = ''
                )

    AND         (
                (
                UPPER(attyinfo.lastname) = @attyLName
    AND         @attyLName IS NOT NULL
    AND         @attyLName <> ''
                )
    OR          @attyLName IS NULL
    OR          @attyLName = ''
                )

    AND         (
                (
                status_chg_dt >= @txnStDate
    AND         @txnStDate IS NOT NULL
                )
    OR          @txnStDate IS NULL
                )

    AND         (
                (
                status_chg_dt <= @txnFnDate
    AND         @txnFnDate IS NOT NULL
                )
    OR          @txnFnDate IS NULL
                )

    RETURN 1
END

逻辑很简单:

如果 Value IS NOT NULL 则与列比较...否则(如果 Value IS NULL)则不比较...

【讨论】:

猜你喜欢
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2019-09-07
  • 2012-07-16
  • 2011-04-26
  • 1970-01-01
相关资源
最近更新 更多