web-dev-qa-db-ja.com

OBJECT_DEFINITIONからの出力をフォーマットしてsp_helptextと同じに見えるようにするにはどうすればよいですか?

object_definitionsp_helptext はどちらもストアドプロシージャのソースコードを返しますが、object_definitionを使用して、改行を含むソースコードをsp_helptextは現在そうですか?

たとえば、次のコードでは、ストアドプロシージャを作成しています。

if OBJECT_ID('usp_radhe') is not null
   drop procedure usp_radhe
go
-- this procedure is just a test
-- it just returns a date in the past
-- how will I get its source code?
create procedure usp_radhe as 
begin
select dateadd(dd,-31,GETDATE()) 
end 

sp_helptextを使用すると、ソースコードの見栄えが良くなります。

sp_helptext 'usp_radhe'

enter image description here

usingobject_definitionソースコードを1行で取得しますが、それは私には適していません。

select OBJECT_DEFINITION(object_id('usp_radhe'))

enter image description here

5

SQL Server 2016を使用しているため、STRING_SPLITAaron Bertrandからのトリック でキャリッジリターン/ラインフィードで分割します。

DECLARE 
  @olddelim nvarchar(32) = char(13) + Char(10),
  @newdelim nchar(1)     = NCHAR(9999); -- pencil (✏)

SELECT * FROM STRING_SPLIT(REPLACE(OBJECT_DEFINITION(object_id('usp_radhe')), @olddelim, @newdelim), @newdelim);
2
Scott Hodgin

同様の問題がありました。最初にSSMSのこのオプションをオンにします-デフォルトではオフになっています。

SSMS/Tools/Options/Query results/SQL Server/Results to grid/Retain CR/LF on copy or save

SSMSを閉じ、再度実行して機能させます。

このクエリを使用して、オブジェクト定義の全文を取得します。

create view v_get_text_of_objects as

select top 100000
  [name]
, definition = replace(replace(object_definition(object_id),'create view','alter view'),'create proc','alter proc')
, len = len(object_definition(object_id)) 
, type
, type_desc
, create_date   
, modify_date
from  sys.objects
where object_definition(object_id) like '%your text to find in sp%'
order by type, create_date desc

SpテキストのLENを表示したいので、トリミングされません。

5
sp_helptext 'sp_helptext'
    --If carriage return found  
    IF @CurrentPos != 0  
    begin  
        /*If new value for @Lines length will be > then the  
        **set length then insert current contents of @line  
        **and proceed.  
        */  
        while (isnull(LEN(@Line),0) + @BlankSpaceAdded + @CurrentPos-@BasePos + @LFCR) > @DefinedLength  
        begin  
            select @AddOnLen = @DefinedLength-(isnull(LEN(@Line),0) + @BlankSpaceAdded)  
            INSERT #CommentText VALUES  
            ( @LineId,  
              isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N''))  
            select @Line = NULL, @LineId = @LineId + 1,  
                   @BasePos = @BasePos + @AddOnLen, @BlankSpaceAdded = 0  
        end  
        select @Line    = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @CurrentPos-@BasePos + @LFCR), N'')  
        select @BasePos = @CurrentPos+2  
        INSERT #CommentText VALUES( @LineId, @Line )  
        select @LineId = @LineId + 1  
        select @Line = NULL  
    end  

K、これがsp_helptextが行う方法です。結果の折り返しは、object_definitionによって返されたCRLF文字の行を返すテーブル関数です。

3
Alocyte

無視する必要がある最上部と最下部の余分な行を気にしない場合は、次を使用して、結果セットではなくテキストとしてフルテキストを表示できます。

SELECT 1 AS [Tag], 0 AS [Parent], NCHAR(13) + NCHAR(10) +
       OBJECT_DEFINITION(OBJECT_ID(N'sys.sp_helptext')) AS [Code!1!!CDATA]
FOR XML EXPLICIT;

SQL Server 2005以降のすべてのバージョンで同じように機能します(まあ、2005、2017、2019のCTP 2.2で機能していたことから、そう思います)。 「CDATA」セクションを使用しました(そのため、EXPLICITモードのFOR XMLを使用する必要があります)。これにより、XMLの「特殊」文字<>&"は、それぞれ&lt;&gt;&amp;&quot;としてエスケープされません。

上記のT-SQLを実行すると、XML値の1行1列の結果セットが返されます。下線が引かれたXML値をクリックすると、新しいタブが開き、適切な形式の完全なテキストが表示されます(最初の行は<Code><![CDATA[、最後の行は]]></Code>):

<Code><![CDATA[
create procedure sys.sp_helptext
@objname nvarchar(776)
,@columnname sysname = NULL
as

set nocount on

declare @dbname sysname

... {redacted for space} ...

select Text from #CommentText order by LineId

CLOSE  ms_crs_syscom
DEALLOCATE  ms_crs_syscom
DROP TABLE  #CommentText

return (0) -- sp_helptext
]]></Code>

「表示」しているアイテムのサイズによっては、プルダウンするXMLデータの量についてSSMS設定を増やす必要がある場合があります(そうでない場合、切り捨てられた結果が表示される場合があります)。移動:

ツール|オプション|クエリ結果| SQL Server |グリッドへの結果

次に、[取得した最大文字数]で[XMLデータ]をに設定します(オプションは1 MB、2 MB、5 MB、無制限)。次に「OK」ボタンをクリックします。

0
Solomon Rutzky

MSSQL Server 2012の場合、再帰関数を使用できます。例えば。:

/* Recursive function, to split an object (like stored procedure) into individual lines, with line number */
declare @delimiter nvarchar(2) = char(10);
declare @objectName sysname = 'dbo.MyObject'

;with CTE as (
  select 
    0 as linenr
  , object_definition( object_id(@objectName)) as def
  , convert(nvarchar(max), N'') as line
  union all
  select 
    linenr + 1
  , substring(def, charindex(@delimiter, def) + len(@delimiter), len(def) - (charindex(@delimiter, def)))
  , left(def, charindex(@delimiter, def)) as line
  from CTE
  where charindex(@delimiter, def) <> 0
 )
select linenr, line
from CTE
where linenr >= 1
OPTION (MAXRECURSION 0);
0
Erwin Anema