参考:我看了SQL Server stored procedure parameters开始。
问题:
我想根据通过存储过程传入的数据制作不同的SQL语句。这个例子涉及一个版本,但会有几个版本,我想保持我的代码一致。
错误:
消息102,级别15,状态1,过程spSearchGrid,第60行 '@SQL'附近的语法不正确。 Msg 103,Level 15,State 4,Procedure spSearchGrid,Line 60 以'SELECT p.ID AS ID,p.UPRN AS UPRN,COALESCE(a.OverallRiskCategory,'Unknown')开头的标识符AS OverallRiskCategory,COALESCE(a.TypeOfUtility,'U'太长。最大长度为128。 消息102,级别15,状态1,过程spSearchGrid,第65行 '@SQL'附近的语法不正确。 Msg 103,Level 15,State 4,Procedure spSearchGrid,66行 以@sDateFrom和@sDateTo之间的'a.SurveyDate开头的标识符AND(p.UPRN LIKE'%'+ @sUPRN +'%'或 p.PostCode LIKE'%'+ @sPostcode +'太长了。最大长度为128。 消息102,级别15,状态1,过程spSearchGrid,第76行 'END'附近的语法不正确。
尝试:
我尝试在外围使用单一和双重语音标记,但这并没有帮助解决问题。
代码:
USE [Database]
GO
/****** Object: StoredProcedure [dbo].[spSearchGrid] Script Date: 18/06/2015 15:14:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
ALTER PROCEDURE [dbo].[spSearchGrid]
@sUPRN varchar(150),
@sPostcode varchar(20),
@sDateFrom datetime,
@sDateTo datetime,
--@sUCARN varchar(20),
@sPropertyName varchar(20),
@sStreet varchar(150),
@sSurveyCompany varchar(150),
@sRiskRating varchar(150),
@sRegion varchar(150)
-- Add the parameters for the stored procedure here
--@test1 VARCHAR(30) OUTPUT
AS
BEGIN
--and
DECLARE @SQL VARCHAR(MAX)
If @sUPRN = 'Test'
BEGIN
@SQL = SELECT p.ID AS ID, p.UPRN AS UPRN, COALESCE(a.OverallRiskCategory,'Unknown') AS OverallRiskCategory, COALESCE(a.TypeOfUtility,'Unknown') AS TypeOfUtility, COALESCE(a.SurveyDate,'') AS SurveyDate, COALESCE(a.ItemRef, '') AS ItemRef, COALESCE(a.NextAsbestosSurveyDue,'') AS NextAsbestosSurveyDue , COALESCE(a.Recommendations,'NO DATA') AS Recommendations, COALESCE(a.StatusOfIssue,'0') As StatusOfIssue
FROM TblProperty AS p LEFT JOIN TblAsbestos AS a on a.UPRN = p.UPRN WHERE
IF LTRIM(RTRIM(@sRiskRating)) = '1234xyz'
@SQL += a.OverallRiskCategory = LTRIM(RTRIM(@sRiskRating)) AND
@SQL += a.SurveyDate between @sDateFrom and @sDateTo AND (p.UPRN LIKE '%' + @sUPRN + '%' or
p.PostCode LIKE '%' + @sPostcode + '%' or
p.ShopName LIKE '%' + @sPropertyName + '%' or
p.Street LIKE '%' + @sStreet + '%' or
p.Reg = @sRegion or
a.SurveyCompany LIKE '%' + @sSurveyCompany + '%' )
END
--PRINT(@SQL)
EXEC(@SQL)
END
答案 0 :(得分:1)
您需要通过在其前添加其他引号来确保您的报价已转义。
此外,初始化@SQL变量时以及当您尝试在IF
部分中向其添加更多代码时会出现一些问题。
试试这个:
USE [Database]
GO
/****** Object: StoredProcedure [dbo].[spSearchGrid] Script Date: 18/06/2015 15:14:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
ALTER PROCEDURE [dbo].[spSearchGrid]
@sUPRN varchar(150),
@sPostcode varchar(20),
@sDateFrom datetime,
@sDateTo datetime,
--@sUCARN varchar(20),
@sPropertyName varchar(20),
@sStreet varchar(150),
@sSurveyCompany varchar(150),
@sRiskRating varchar(150) = NULL,
@sRegion varchar(150)
-- Add the parameters for the stored procedure here
--@test1 VARCHAR(30) OUTPUT
AS
BEGIN
--and
DECLARE @SQL VARCHAR(MAX)
If @sUPRN = 'Test'
BEGIN
SET @SQL = 'SELECT p.ID AS ID, p.UPRN AS UPRN, COALESCE(a.OverallRiskCategory,''Unknown'') AS OverallRiskCategory, COALESCE(a.TypeOfUtility,''Unknown'') AS TypeOfUtility, COALESCE(a.SurveyDate,'''') AS SurveyDate, COALESCE(a.ItemRef, '''') AS ItemRef, COALESCE(a.NextAsbestosSurveyDue,'''') AS NextAsbestosSurveyDue , COALESCE(a.Recommendations,''NO DATA'') AS Recommendations, COALESCE(a.StatusOfIssue,''0'') As StatusOfIssue
FROM TblProperty AS p LEFT JOIN TblAsbestos AS a on a.UPRN = p.UPRN WHERE'
IF LTRIM(RTRIM(@sRiskRating)) = '1234xyz'
BEGIN
SET @SQL = @SQL + 'a.OverallRiskCategory = LTRIM(RTRIM(@sRiskRating)) AND '
SET @SQL = @SQL + 'a.SurveyDate between @sDateFrom and @sDateTo AND (p.UPRN LIKE ''%'' + @sUPRN + ''%'' or
p.PostCode LIKE ''%'' + @sPostcode + ''%'' or
p.ShopName LIKE ''%'' + @sPropertyName + ''%'' or
p.Street LIKE ''%'' + @sStreet + ''%'' or
p.Reg = @sRegion or
a.SurveyCompany LIKE ''%'' + @sSurveyCompany + ''%'' )'
END
END
--PRINT(@SQL)
EXEC(@SQL)
END
答案 1 :(得分:0)
我在这里看不到动态sql的需求。您拥有的是基于某些参数的具有多个执行路径的过程。这很常见,你真的不需要求助于动态。原始逻辑似乎存在一些逻辑问题。如果@sUPRN的值不是'测试'这个程序没有做任何事情。我猜这是不正确的,但这取决于OP来确定。
将所有这些逻辑保留在一个程序中是可行的,但它会有轻微的性能损失。因为您需要执行两个不同的查询,所以您可能需要针对不同查询执行计划。实现此目的的一种方法(我将很快发布的方式)是为您的查询添加重新编译选项。这会强制优化器在运行后抛弃执行计划,因此它总是会得到一个新的编译。这意味着每次运行此过程时,都必须首先重新编译它。一个更好的方法,我将在我的系统上采用的方法是为每个路径创建一个子过程。这允许为每个分支缓存计划。
以下是如何在没有任何动态sql的情况下执行此操作并保持性能良好。
ALTER PROCEDURE [dbo].[spSearchGrid]
(
@sUPRN varchar(150),
@sPostcode varchar(20),
@sDateFrom datetime,
@sDateTo datetime,
@sPropertyName varchar(20),
@sStreet varchar(150),
@sSurveyCompany varchar(150),
@sRiskRating varchar(150) = NULL,
@sRegion varchar(150)
) AS
BEGIN
SET NOCOUNT ON
If @sUPRN = 'Test'
IF LTRIM(RTRIM(@sRiskRating)) = '1234xyz'
SELECT p.ID AS ID
, p.UPRN AS UPRN
, COALESCE(a.OverallRiskCategory, 'Unknown') AS OverallRiskCategory
, COALESCE(a.TypeOfUtility, 'Unknown') AS TypeOfUtility
, COALESCE(a.SurveyDate, '') AS SurveyDate --Is this really a date? If so, this will become 1/1/1900
, COALESCE(a.ItemRef, '') AS ItemRef
, COALESCE(a.NextAsbestosSurveyDue, '') AS NextAsbestosSurveyDue
, COALESCE(a.Recommendations, 'NO DATA') AS Recommendations
, COALESCE(a.StatusOfIssue, '0') As StatusOfIssue
FROM TblProperty AS p
LEFT JOIN TblAsbestos AS a on a.UPRN = p.UPRN
WHERE a.OverallRiskCategory = LTRIM(RTRIM(@sRiskRating))
AND a.SurveyDate between @sDateFrom and @sDateTo
AND
(
p.UPRN LIKE '%' + @sUPRN + '%'
OR p.PostCode LIKE '%' + @sPostcode + '%'
OR p.ShopName LIKE '%' + @sPropertyName + '%'
OR p.Street LIKE '%' + @sStreet + '%'
OR p.Reg = @sRegion
OR a.SurveyCompany LIKE '%' + @sSurveyCompany + '%'
)
OPTION (RECOMPILE)
ELSE
SELECT p.ID AS ID
, p.UPRN AS UPRN
, COALESCE(a.OverallRiskCategory, 'Unknown') AS OverallRiskCategory
, COALESCE(a.TypeOfUtility, 'Unknown') AS TypeOfUtility
, COALESCE(a.SurveyDate, '') AS SurveyDate --Is this really a date? If so, this will become 1/1/1900
, COALESCE(a.ItemRef, '') AS ItemRef
, COALESCE(a.NextAsbestosSurveyDue, '') AS NextAsbestosSurveyDue
, COALESCE(a.Recommendations, 'NO DATA') AS Recommendations
, COALESCE(a.StatusOfIssue, '0') As StatusOfIssue
FROM TblProperty AS p
LEFT JOIN TblAsbestos AS a on a.UPRN = p.UPRN
OPTION (RECOMPILE)
--there is nothing to do if @sUPRN is not 'Test'???
END
Gail Shaw在她的博客上发表了一篇关于这个主题的优秀文章。她也更喜欢把它分成3个程序,但我没有在这里做。阅读本文并自行决定哪些适合您。 http://sqlinthewild.co.za/index.php/2009/09/15/multiple-execution-paths/