2016-03-02 90 views
0

我正在嘗試在SQL Server中編寫一個SP,它需要4個輸入參數並返回基於參數將具有WHERE語句的查詢的結果。我試圖使用sp_executeSql爲此,但不斷收到以下錯誤:T-SQL中的sp_executeSQL錯誤

Msg 102,Level 15,State 1,Line 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' 
+0

** ** DECLARE @txnStDate ... **'是什麼?這不是有效的語法,這就是你得到錯誤的原因。如果您正在嘗試對其進行註釋,請使用'/*...*/',但是在您的代碼中實際使用'@ txnStDate'時,應該刪除'**'。 – Munir

+0

fyi:'IF((LEN(@txnStDate)> 0)AND(LEN(@txnStDate)> 0))'檢查同一個變量兩次,然後使用一個不同的變量('@ txnFnDate')。 – HABO

+0

@HABO - 非常棒!它應該是: ((LEN(@txnStDate)> 0)AND(LEN(@txnFnDate)> 0)) – user6009780

回答

0

爲什麼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 

的邏輯非常簡單:

如果值不爲空,然後用柱比較...否則(如果值爲NULL),則不能比擬的...

+0

您應該閱讀本文以瞭解如何更快地進行此類查詢。 http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/ –

+0

好文章...謝謝! –