Tsql 如何将参数传递给sp内的公共表表达式?
我想使用CTE(公共表表达式)重写一个运行正常但速度较慢的存储过程 我有一个大的存储过程,在这个过程中,我根据使用的参数构建必要的SQL动态。目前有27个参数,我组成了SQL字符串,在最后执行,它看起来像:Tsql 如何将参数传递给sp内的公共表表达式?,tsql,stored-procedures,common-table-expression,Tsql,Stored Procedures,Common Table Expression,我想使用CTE(公共表表达式)重写一个运行正常但速度较慢的存储过程 我有一个大的存储过程,在这个过程中,我根据使用的参数构建必要的SQL动态。目前有27个参数,我组成了SQL字符串,在最后执行,它看起来像: DECLARE @SqlWhereClause NVARCHAR(MAX) SET @SqlWhereClause = ' WHERE ([InTimeStamp] BETWEEN ''' + CONVERT(VARCHAR(19), @fromDate, 120) + '''
DECLARE @SqlWhereClause NVARCHAR(MAX)
SET @SqlWhereClause = ' WHERE ([InTimeStamp] BETWEEN ''' + CONVERT(VARCHAR(19), @fromDate, 120) + ''' AND ''' + CONVERT(VARCHAR(19), @toDate, 120) + ''')'
IF @showOnlyErrors = '1'
BEGIN
SET @SqlWhereClause += ' AND Status = ''Error'''
END
IF LEN(LTRIM(RTRIM(@docNo))) > 0
BEGIN
IF @matchExact = '1'
BEGIN
SET @SqlWhereClause += ' AND DocumentNumber = ''' + @docNo + ''''
END
ELSE
BEGIN
SET @SqlWhereClause += ' AND (contains([DocumentNumber],'''+ @docNo +'''))'
END
END
最后,我添加分页并将其转换为最终的formSQL:
IF CONVERT(int, LTRIM(RTRIM(@takeRows))) > 0
BEGIN
SET @SqlOrderByClause += ' OFFSET ' + @rowNumberToSkip +' ROWS FETCH NEXT '+ @takeRows +' ROWS ONLY '
Set @RowCount = ' Select @totalRecords = count(1) from dbo.Messages WITH (NOLOCK) ' + @SqlWhereClause
END
SET @SQL = @SqlSelect + @SqlFrom + @SqlWhereClause + @SqlOrderByClause + ' ; ' + @RowCount
PRINT @SQL
EXECUTE sp_executesql @SQL, @params, @totalRecords OUTPUT
每件事都像一个符咒一样起作用。没问题。只有性能问题。为了解决其中一个问题,我将尝试使用CTE(公共表扩展)
但这是行不通的:
With DataSQL AS
(@SqlSelect + @SqlFrom + @SqlWhereClause + @SqlOrderByClause),
- incorrect syntax near @SqlSelect - Expecting '(' or Select.
我也试过这个:
WITH DataSQL AS
( Select @SqlSelect From @SqlFromFast
Where @SqlWhereClause Order By @SqlOrderByClause),
我得到:
An expression of non-boolean type specified in a context where a condition is expected, near 'Order'
有什么想法吗?或者不可能对多个变量使用CTE?到目前为止,我只找到了一个或两个变量的查询。您可以尝试:
WITH DataSQL AS
(
SELECT @SqlSelect SqlSelect
, @SqlFromFast SqlFromFast
, etcetera
)
请确保您提供别名,否则它将无法工作。不过,我怀疑这会对您的性能问题有所帮助。你可以试着使用临时表,这通常更快。您还可以尝试使用内部变量:
DECLARE @Select VARCHAR(MAX) = @SQLSelect
而使用它们,这可能会帮助优化器,尽管这取决于您的数据。什么是慢的?构建动态sql或执行动态sql?执行需要很长时间。另外,因为行数几乎和查询本身一样多。我在执行计划中查过,它有50%/50%你看过执行计划了吗?SSM是否建议使用任何索引?索引的问题在于,一方面我们有许多包含(如)搜索,其中索引没有帮助,另一方面,在总共27个搜索标准中,通常使用12-15个搜索标准。但其他的也在使用中。此表已经是一个聚合表,仅用于监视目的,因此更新不存在,插入通过批处理(每5分钟一次)完成,删除通过作业完成(删除所有早于52周的数据)。目前我检测到的最大瓶颈是@RowCount的第二个查询。它所用的时间与查询本身差不多。变量SqlSelect包含的不仅仅是一列,与SQLWHEREQUALE变量相同。设置@SqlSelect='[RecordId]、[TransactionId]、[Status]、[InTimeStamp]、[OutTimeStamp]、[Doctype]、[DocumentNumber]、[DocFormat]、。。。。。