web-dev-qa-db-fra.com

Comment formater la sortie de OBJECT_DEFINITION pour qu'elle ressemble à sp_helptext?

object_definition et sp_helptext renvoient tous les deux le code source d'une procédure stockée - mais comment puis-je utiliser object_definition et obtenez le code source, y compris les sauts de ligne, comme sp_helptext le fait actuellement?

par exemple dans le code ci-dessous je crée une procédure stockée:

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 

en utilisant sp_helptext j'obtiens une belle vue du code source:

sp_helptext 'usp_radhe'

enter image description here

en utilisant définition_objet j'obtiens le code source sur une seule ligne et ce n'est pas bon pour moi:

select OBJECT_DEFINITION(object_id('usp_radhe'))

enter image description here

5
Marcello Miorelli

Puisque vous utilisez SQL Server 2016, vous pouvez utiliser STRING_SPLIT et un astuce d'Aaron Bertrand à partager sur retour chariot/saut de ligne.

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

J'ai eu un problème similaire. Activez d'abord cette option de SSMS - elle est désactivée par défaut:

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

Fermez SSMS et exécutez-le à nouveau pour le faire fonctionner.

J'utilise cette requête pour obtenir le texte intégral des définitions d'objet:

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

J'aime afficher LEN du texte sp, de sorte que je suis sûr qu'il n'est pas recadré.

5
Przemyslaw Remin
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, c'est ainsi que le fait sp_helptext. Envelopper les résultats sont une fonction de table renvoyant des lignes pour les caractères CRLF renvoyés par la définition_objet.

3
Alocyte

Si cela ne vous dérange pas une ligne supplémentaire tout en haut et en bas qui doit être ignorée, vous pouvez utiliser ce qui suit pour afficher le texte intégral, sous forme de texte et non comme un ensemble de résultats:

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;

Il fonctionne de la même manière dans toutes les versions à partir de SQL Server 2005 (enfin, je suppose qu'en voyant qu'il a fonctionné sur 2005, 2017 et 2019 CTP 2.2). J'ai utilisé une section "CDATA" (qui, à son tour, nécessite l'utilisation du mode EXPLICIT de FOR XML) pour que les caractères XML "spéciaux" <, >, &, et " ne serait pas échappé en tant que &lt;, &gt;, &amp;, et &quot;, respectivement.

Si vous exécutez le T-SQL illustré ci-dessus, vous récupérerez un jeu de résultats d'une ligne et d'une colonne d'une valeur XML. Cliquez sur la valeur XML soulignée et elle s'ouvrira dans un nouvel onglet affichant le texte complet et correctement formaté (avec une première ligne de <Code><![CDATA[ et une dernière ligne de ]]></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>

Selon la taille de l'élément que vous "affichez", vous devrez peut-être augmenter le paramètre SSMS pour la quantité de données XML qu'il extrait (sinon vous pourriez voir des résultats tronqués). Aller à:

Outils | Options | Résultats de la requête | SQL Server | Résultats vers la grille

Ensuite, sous "Nombre maximal de caractères récupérés", définissez "Données XML" sur (les options sont: 1 Mo, 2 Mo, 5 Mo et Illimité). Cliquez ensuite sur le bouton "OK".

0
Solomon Rutzky

Pour MSSQL Server 2012, vous pouvez utiliser une fonction récursive. Par exemple.:

/* 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