我正在尝试在SQL Server中编写一个SP,它接受4个输入参数并返回一个查询结果,该查询将根据参数生成一个WHERE语句。我正在尝试使用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 :(得分: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
逻辑非常简单:
如果Value IS NOT NULL,则与列进行比较... else(如果Value IS NULL)则不比较......