2017-10-12 49 views
0

我有一个查询为搜索存储过程和意见,但忽略评论

select 
    definition 
from 
    sys.objects so 
join 
    sys.sql_modules ssmsp on so.[object_id] = ssmsp.[object_id] 
where 
    so.type in ('v', 'p') 
where 
    definition like '%exec%' 

在填充记录,会从评论人口也。我怎样才能避免从评论中过滤掉?

有没有解决方法?

谢谢

+1

的可能重复[我怎样才能找到一个特定的字符串代码,而不是在评论( https://stackoverflow.com/questions/11928306/how-can-i-find-code-with-a-specific-string-but-not-in-comments) –

回答

0

我认为这将是几乎不可能实现在一个单一的查询。

请记住,[定义]没有格式化,没有换行符等,代码是单行(复制并粘贴到编辑器中)。

如果评论始于--那么它在哪里结束?你无法知道。

由于您可以找到相应的*/,所以使用/*稍微容易一些,但是仍然存在多次出现搜索字符串的复杂情况。

您可能必须使用PATINDEX并指定你整理区分大小写的版本(如果你有一个不区分大小写的数据库)多一点运气,比如你知道你只想要EXEC,而不是出现“执行”例如WHERE patindex('%EXEC%',defintion COLLATE SQL_Latin1_General_CP1_CS_AS) > 0

+0

如果你选择你的结果文本而不是一个格的格式是p保留,如[如何在SQL Server中包含syscomments的换行符?](https://stackoverflow.com/questions/1975468/how-do-i-include-the-newlines-from-syscomments-in- SQL服务器)。 – Brett

0

首先使用快速varchar(max)字符串“splitter”。以下是Jeff Moden的delimitedSplit8K的黑客版本。

IF OBJECT_ID('dbo.DelimitedSplit2B','IF') IS NOT NULL DROP FUNCTION dbo.DelimitedSplit2B; 
GO 
CREATE FUNCTION dbo.DelimitedSplit2B 
(
    @pString varchar(max), 
    @pDelimiter char(1) 
) 
RETURNS TABLE WITH SCHEMABINDING AS RETURN 
WITH L1(N) AS 
(
    SELECT N 
    FROM (VALUES 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), 
    (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(N) 
), --216 values 
cteTally(N) AS 
(
    SELECT 0 UNION ALL 
    SELECT TOP (DATALENGTH(ISNULL(@pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
    FROM L1 a CROSS JOIN L1 b CROSS JOIN L1 c 
    --2,176,782,336 rows: enough to handle 2,147,483,647 characters (the varchar(max) limit) 
), 
cteStart(N1) AS 
(
    SELECT t.N+1 
    FROM cteTally t 
    WHERE (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0) 
) 
SELECT 
    ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1), 
    Item = SUBSTRING(@pString,s.N1,ISNULL(NULLIF((LEAD(s.N1,1,1) 
      OVER (ORDER BY s.N1) - 1),0)-s.N1,DATALENGTH(ISNULL(@pString,1)))) 
FROM cteStart s; 

下一步的功能来搜索您的DDL

create function dbo.SearchObjectDDLFor (@searchstring varchar(100), @maxLen int) 
returns table as return 
select objectName, lineNumber, lineText 
from 
(
    select 
    objectName = ss.[name]+'.'+so.[name], 
    lineNumber = itemnumber, 
    lineText  = substring(t.item, 1, isnull(nullif(charindex('--', t.item),0)-1, 8000)), 
    isLongComment = 
    sum 
    (-- this will assign a 1 for everything 
     case when t.item like '/*%' then 1 
      when t.item like '*/%'then -1 
      else 0 end 
    ) over (partition by so.[name] order by itemnumber) 
    from sys.objects so 
    join sys.sql_modules ssmsp on so.[object_id] = ssmsp.[object_id] 
    join sys.schemas ss on so.schema_id = ss.schema_id 
    cross apply dbo.delimitedSplit2B(definition, char(10)) 
    cross apply (values (rtrim(ltrim(replace(item,char(13),''))))) t(item) 
    where so.type in ('v', 'p') 
    and len(definition) < isnull(@maxLen,100000) -- character limit is @maxLen (100K default) 
) splitLines 
where isLongComment = 0 and lineText not like '--%' and lineText <> '*/' 
and lineText like '%'[email protected]+'%'; 

此功能:

  1. 接受输入要搜索的字符串(@searchstring)
  2. 将您的对象成行
  3. 仅返回第e部分行不是注释
  4. 将步骤3中创建的行过滤为包含@searchstring的行,并返回ObjectName(。),行号和文本。

注意事项:

  1. 我只是把这个一起快速所以请原谅任何错误

  2. 一个T-SQL分路器接受[N] VARCHAR(最大值)将是缓慢的。 CLR分离器可能会更快,但我们并不是在谈论数百万行。也就是说,你可以通过使用@maxLen过滤行数来加速它。 @maxlen说:“忽略和更多@maxLen行数的对象。”当它为空时,它将搜索长达100K行的对象(但可以调整)。

  3. 这个函数地址评论场景中的意见看有没有“ - ”字符串中的任何地方:其中嵌套上线“/ ”和“ \之间的意见和方案 需要几个方案更多的编码来抑制意见包括:

select col1, /* skipping col2 for now */ col3, col4 

/********* 
comments here 
*********/ 

例子:

select * from dbo.SearchObjectDDLFor('nocount', NULL); 
select * from dbo.SearchObjectDDLFor('nocount', 2000); 

结果看起来类似:

enter image description here