Cette liste de procédures et de fonction permet de rechercher ou de décrire les objets de votre base de données MS SQL Server.
Elle utilise essentiellement des commandes Transact SQL.
1 – Recherche d’une table (ou d’une vue) dans toutes les bases
USE master;
GO
CREATE PROCEDURE dbo.sp__SEARCH_TABLE_ALL_SERVER
@SCHEMA NVARCHAR(128),
@TABLE NVARCHAR(128),
@JOKER BIT,
@ESCAPE NCHAR(1)
AS
/******************************************************************************
* MODULE : META *
* NATURE : PROCEDURE *
* OBJECT : master.dbo.sp__SEARCH_TABLE_ALL_SERVER *
* CREATE : 2018-05-28 *
* VERSION : 1 *
*******************************************************************************
* Frédéric BROUARD - alias SQLpro - SARL SQL SPOT - SQLpro@sqlspot.com *
* Architecte de données : expertise, audit, conseil, formation, modélisation *
* tuning, sur les SGBD Relationnels, le langage SQL, MS SQL Server/PostGreSQL *
* blog: http://mssqlserver.fr website: http://sqlpro.developpez.com *
* Most Valuable Professional - MVP - SQL Server (data platform) depuis 2004 *
*******************************************************************************
* PURPOSE : search a user<code>s table in all the databases of an instance *
*******************************************************************************
* INPUTS : *
* @SCHEMA NVARCHAR(128) the name of the table</code>s schema in which we search *
* @TABLE NVARCHAR(128) the name of the table to be search *
* @JOKER BIT if 1 use LIKE and accepts LIKE`s jokers *
* @ESCAPE NCHAR(1) nchar for escpaping from LIKE *
*******************************************************************************
* OUPUT : table as describe : *
* TABLE_CATALOG sysname the database name *
* TABLE_SCHEMA sysname the table schema name *
* TABLE_NAME sysname the table name *
* TABLE_TYPE varchar(10) the table type (BASE TABLE or VIEW) *
*******************************************************************************
* RUNNABLE : version 2008 and superior *
*******************************************************************************
* SAMPLES : *
* EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'LOT', NULL, NULL *
* EXEC sp__SEARCH_TABLE_ALL_SERVER 'dbo', 'LOT', NULL, NULL *
* EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'LOT%', 1, NULL *
* EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'T?_%', 1, '?' *
******************************************************************************/
DECLARE @SQL NVARCHAR(max);
SET @SQL = N'';
SET @SCHEMA = COALESCE('''' + @SCHEMA + '''', 'NULL');
SELECT @SQL = @SQL
+ N'SELECT TABLE_CATALOG COLLATE SQL_Latin1_General_CP850_BIN AS [DATABASE_NAME], '
+ N'TABLE_SCHEMA COLLATE SQL_Latin1_General_CP850_BIN AS TABLE_SCHEMA, '
+ N'TABLE_NAME COLLATE SQL_Latin1_General_CP850_BIN AS TABLE_NAME, '
+ N'TABLE_TYPE COLLATE SQL_Latin1_General_CP850_BIN AS TABLE_NAME FROM ['
+ name + N'].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA '
+ CASE @JOKER WHEN 1
THEN N'LIKE '
ELSE N'= '
END + N' COALESCE(' + @SCHEMA + N', TABLE_SCHEMA) '
+ CASE WHEN @JOKER = 1 AND @ESCAPE IS NOT NULL
THEN 'ESCAPE ''' + @ESCAPE + ''''
ELSE N'' END + N' AND TABLE_NAME '
+ CASE @JOKER WHEN 1
THEN N'LIKE '
ELSE N'= '
END + '''' + @TABLE + N''' '
+ CASE WHEN @JOKER = 1 AND @ESCAPE IS NOT NULL
THEN 'ESCAPE ''' + @ESCAPE + ''''
ELSE N'' END + N' UNION ALL '
FROM sys.databases;
SET @SQL = LEFT(@SQL, LEN(@SQL) - 10);
PRINT @SQL
EXEC (@SQL);
GO
EXEC sp_MS_marksystemobject 'sp__SEARCH_TABLE_ALL_SERVER';
Cette procédure « système »(1) est utilisable depuis n’importe quelle base et recherche dans toutes les bases, y compris les bases systèmes, une table dont le nom ou le nom et le schéma sont passé en argument. Si le nom du schéma n’est pas donnée, alors la procédure recherche à travers tous les schémas de toutes les bases. Vous pouvez utiliser les joker du like en passant la valeur de l’argument JOKER à 1 et même prévoir un caractère d’échappement en le précisant dans la valeur de l’argument ESCAPE.
Exemples d’utilisation :
EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'LOT', NULL, NULL; EXEC sp__SEARCH_TABLE_ALL_SERVER 'dbo', 'LOT', NULL, NULL; EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'LOT%', 1, NULL; EXEC sp__SEARCH_TABLE_ALL_SERVER NULL, 'T?_%', 1, '?';
Le lien de téléchargement du code
2 – Suppression de tout commentaires et caractères non imprimable dans du code d’une routine
CREATE FUNCTION dbo.F_META_PURGE_CODE
(@SQL NVARCHAR(max))
RETURNS NVARCHAR(max)
WITH RETURNS NULL ON NULL INPUT
AS
/******************************************************************************
* MODULE : META *
* NATURE : SCALAR_FUNCTION *
* OBJECT : dbo.F_META_PURGE_CODE *
* CREATE : 2018-05-28 *
* VERSION : 1 *
*******************************************************************************
* Frédéric BROUARD - alias SQLpro - SARL SQL SPOT - SQLpro@sqlspot.com *
* Architecte de données : expertise, audit, conseil, formation, modélisation *
* tuning, sur les SGBD Relationnels, le langage SQL, MS SQL Server/PostGreSQL *
* blog: http://mssqlserver.fr website: http://sqlpro.developpez.com *
* Most Valuable Professional - MVP - SQL Server (data platform) depuis 2004 *
*******************************************************************************
* PURPOSE : purges Transact SQL code of comments and unprintable characters *
*******************************************************************************
* INPUTS : *
* @SQL NVARCHAR(max) : the Transact SQL code to be purged *
*******************************************************************************
* OUPUT : VARCHAR(max) *
*******************************************************************************
* RUNNABLE : version 2000 and superior *
*******************************************************************************
* SAMPLE : *
* SELECT object_id, definition, *
* dbo.F_META_PURGE_CODE(definition) *
* FROM sys.sql_modules; *
******************************************************************************/
BEGIN
IF @SQL = N'' -- on empty string return empty string
RETURN N'';
DECLARE @NC1 NCHAR(1), -- char to be treated
@NC2 NCHAR(2), -- 2 chars to be treated
@I INT, -- pos of char to be treated
@OUT NVARCHAR(max), -- returned string
@TT BIT, -- 1 if comment as «--»
@SE INT, -- n if comment as «/* */» (can be nested !)
@CC BIT; -- 1 if in as string
-- first assignements
SELECT @OUT = N'', -- output is empty string to begin
@I = 1, -- position of first char
@TT = 0, -- on the beginning, no comment «--»
@SE = 0, -- on the beginning, no comment «/*»
@CC = 0; -- on the beginning, no string"
-- loop while there is a char to treat
WHILE @I <= LEN(@SQL)
BEGIN
-- getting the chars
SELECT @NC2 = SUBSTRING(@SQL, @I, 2), -- get the 2 chars at position I
@NC1 = SUBSTRING(@SQL, @I, 1); -- get the char at position I
-- this is the beginning or the ending of a string (not in comment)
-- so we reverse the position of the bit @CC
IF @NC1 = '''' AND @TT = 0 AND @SE = 0
IF @CC = 1
SET @CC = 0
ELSE
SET @CC = 1;
-- we are in a string, add the char in the output and loop again
IF @CC = 1
BEGIN
SET @OUT = @OUT + @NC1
SET @I = @I + 1;
CONTINUE;
END
-- we are not in a string neither in a comment, and the next 2 chars are
-- not a comment's beginning. Add the char in the output and loop again
IF @TT = 0 AND @SE = 0 AND @CC = 0 AND @NC2 NOT IN (N'--', '/*')
BEGIN
SET @OUT = @OUT + @NC1
SET @I = @I + 1;
CONTINUE;
END
-- we are not in "--" comment and the next 2 chars are a "/*" comment
-- increments "/*" counter and pass 2 chars
IF @TT = 0 AND @NC2 = NCHAR(47) + NCHAR(42)
BEGIN
SELECT @SE = @SE + 1,
@I = @I + 2;
CONTINUE;
END;
-- we are not in "/*" comment and the next 2 chars are a "--" comment
-- set "--" bit to 1 and pass 2 chars
IF @TT = 0 AND @SE = 0 AND @NC2 = N'--'
BEGIN
SELECT @TT = 1,
@I = @I + 2;
CONTINUE;
END;
-- we are in "/*" comment and the next 2 chars are a "*/" comment end
-- decrease the "/*" counter and pass 2 chars
IF @TT = 0 AND @SE > 0 AND @NC2 = NCHAR(42) + CHAR(47)
BEGIN
SET @SE = @SE - 1;
SET @I = @I + 2;
CONTINUE;
END;
-- we are in "--" comment and the next 1 or 2 chars are a "--" comment end
-- set "--" bit to 1 and pass 1 or 2 chars
IF @TT = 1 AND @SE = 0 AND @NC1 IN (NCHAR(13), NCHAR(10))
BEGIN
SET @TT = 0
IF @NC2 = NCHAR(13) + NCHAR(10)
SET @I = @I + 2
ELSE
SET @I = @I + 1
CONTINUE;
END;
-- in all other conditions pass one char
SET @I = @I + 1;
END;
-- clear the string for remaining ends of line or tab
SET @OUT = REPLACE(REPLACE(REPLACE(@OUT, NCHAR(9), N' '),
NCHAR(10), N' '),
NCHAR(13), N' ');
-- clear the string of duplicate spaces except in a string (' ') or in a bracketed SQL identifier
DECLARE @KK BIT = 0, -- identifies if we are in a SQL identifier with brackets [...]
@EE BIT = 0; -- identifies if we are in a string ' ... '
-- initializing
SELECT @SQL = @OUT,
@I = 0,
@CC = 0,
@OUT = N'';
-- loop over the chars
WHILE @I <= LEN(@SQL)
BEGIN
SET @I = @I + 1;
SET @NC1 = SUBSTRING(@SQL, @I, 1);
-- beginning of an identifier with brackets
IF @NC1 = '[' AND @KK = 0 AND @CC = 0
BEGIN
SELECT @KK = 1, @EE = 0;
SET @OUT = @OUT + @NC1
CONTINUE;
END;
-- ending of an identifier with brackets
IF @NC1 = ']' AND @KK = 1
BEGIN
SELECT @KK = 0, @EE = 0;
SET @OUT = @OUT + @NC1
CONTINUE;
END;
-- beginning of a string with simple quote
IF @NC1 = '''' AND @KK = 0 AND @CC = 0
BEGIN
SELECT @CC = 1, @EE = 0;
SET @OUT = @OUT + @NC1
CONTINUE;
END;
-- ending of a string with simple quote
IF @NC1 = '''' AND @CC = 1
BEGIN
SELECT @CC = 0, @EE = 0;
SET @OUT = @OUT + @NC1
CONTINUE;
END;
-- firts space we keep it always
IF @NC1 = ' ' AND @EE = 0
BEGIN
SET @OUT = @OUT + @NC1
SET @EE = 1;
CONTINUE
END
-- space following a space, in bracketed identifier or string
IF @NC1 = ' ' AND @EE = 1 AND (@KK = 1 OR @CC = 1)
BEGIN
SET @OUT = @OUT + @NC1
CONTINUE
END
-- space following a space, outside bracketed identifier or string
IF @NC1 = ' ' AND @EE = 1 AND @KK = 0 AND @CC = 0
BEGIN
CONTINUE
END
-- no more spaces
IF @NC1 <> ' ' AND @EE = 1
SET @EE = 0;
SET @OUT = @OUT + @NC1;
END;
-- trim both the string
RETURN RTRIM(LTRIM(@OUT));
END
GO
Cette fonction purge le code de tous les commentaires présent dans les routines, commentaires commençant par — ou encadrés par /* … */ ainsi que les caractères non imprimables que sont les retours chariot, fin de ligne et tabulation. Enfin, il expurge tous les espaces en double.
Exemple :
SELECT object_id, definition,
dbo.F_META_PURGE_CODE(definition)
FROM sys.sql_modules;
Le lien de téléchargement du code
3 – Procédure de description des index sp__helpindex
Tous les aficionados de SQL Server connaissent la procédures sp_helpindex qui permet de trouver les index d’une table, mais cette dernière n’a jamais été remise au goût du jour, malgré que les index aient notablement évolués : clause INCLUDE, clauses WHERE index fulltext ou géographiques, stockage sur une partition, index columnstore.
La procédure sp__helpindex données ci dessous répare ces manques (notez le double blanc souligné !
CREATE PROCEDURE dbo.sp__HELPINDEX @OBJ NVARCHAR(133)
AS
/******************************************************************************
* METADONNÉES DES INDEX *
* Procédure listant sous forme de tables les métadonnées logique des index *
*******************************************************************************
* Frédéric BROUARD - alias SQLpro - SARL SQL SPOT - SQLpro@sqlspot.com *
* Architecte de données : expertise, audit, conseil, formation, modélisation *
* tuning, sur les SGBD Relationnels, le langage SQL, MS SQL Server/PostGreSQL *
* blog: http://mssqlserver.fr website: http://sqlpro.developpez.com *
* Most Valuable Professional - MVP - SQL Server (data platform) depuis 2004 *
*******************************************************************************
* Cette procédure prend en argument le nom d'une table avec son schéma SQL *
* (sinon le schéma par défaut de l'utilisateur qui la lance) et renvoie un *
* jeu de données contenant le descriptif logique de constitution d'un index *
* ou de tous les index de la base *
* NOTA substitut à la procédure stockée système sp_helpindex *
*******************************************************************************
* ATTENTION : procédure système ! Exécutable depuis n'importe quelle base *
* *
* Paramètre en entrée : *
* @OBJ type NVARCHAR(133) : nom de table dont on veut connaître les index *
* si vide, la procédure renvoie la liste de tous les index *
* *
* COLONNE de la table en sortie : *
* TABLE_NAME : nom de la table en deux parties (schéma SQL + nom) *
* INDEX_NAME : nom de l'index (1) *
* INDEX TYPE : type d'index *
* INDEX_STORAGE : type et nom de l'espace de stockage *
* INDEX_KEY : liste des colonnes composant la clef d'index (2) *
* INDEX_INCLUDE : liste des colonnes incluses (3) *
* INDEX_FILTER : filtre d'index s'il y a lieu *
* INDEX_WITH : principaux paramètres de la clause WITH *
* *
* NOTA : *
* (1) certains index n'ont pas de nom. C'est le cas des index "fulltext" *
* (2) certains index n'ont pas de clef. C'est le cas des index *
* "columnstore" et "fulltext". Dans ce cas les colonnes indexées *
* figurent dans la clause INDEX_INCLUDE *
* (3) pour les index CLUSTERED de type BTree, toutes les colonnes autre *
* que celles de la clef étant présente, la valeur présentée est : *
* * - (INDEX_KEY) *
* pour les index CLUSTERED COLUMNSTORE toutes les colonnes de la table *
* étant présente, la valeur présentée est : * *
* *
* EXEMPLE : *
* EXEC dbo.sp__HELPINDEX NULL *
* ... donne la liste de tous les index de la base ... *
* EXEC dbo.sp__HELPINDEX '[client]' *
* ... donne la liste des index de la table client ... *
* EXEC dbo.sp__HELPINDEX 'ventes.client' *
* ... donne la liste des index de la table client du schéma SQL vente... *
* *
******************************************************************************/
SET NOCOUNT ON;
WITH
T0 AS
(
SELECT i."type", s.name + '.' + o.name AS TABLE_NAME,
i.name AS INDEX_NAME,
CASE WHEN i.is_unique = 1 THEN 'UNIQUE ' ELSE '' END +
CASE WHEN xi.xml_index_type = 0 THEN 'PRIMARY ' ELSE '' END +
i.type_desc + CASE WHEN xi.xml_index_type > 0
THEN ' FOR ' + xi.secondary_type_desc ELSE ''
END AS INDEX_TYPE,
COALESCE('FILEGROUP: ' + fg.name,
'PARTITION: ' + ps.name COLLATE database_default +'('
+ STUFF((SELECT N', ' + cp.name
FROM sys.index_columns AS icp
LEFT OUTER JOIN sys.columns AS cp
ON icp.object_id = cp.object_id
AND icp.column_id = cp.column_id
WHERE icp.object_id = i.object_id
AND icp.index_id = i.index_id
AND icp.partition_ordinal >= 1
ORDER BY icp.partition_ordinal
FOR XML PATH(N'')), 1, 1,'') +')' )
AS INDEX_STORAGE,
LTRIM(STUFF((SELECT N', ' + CONCAT(c.name, ' '
+ CASE
WHEN i.type_desc
IN ('XML',
'SPATIAL',
'COLUMNSTORE')
THEN ''
WHEN is_descending_key = 1
THEN 'DESC'
WHEN is_descending_key = 0
THEN 'ASC'
ELSE ''
END)
FROM sys.index_columns AS ic
JOIN sys.columns AS c
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
WHERE ic.object_id = i.object_id
AND ic.index_id = i.index_id
AND is_included_column = 0
ORDER BY key_ordinal
FOR XML PATH(N'')), 1, 1,'')) AS INDEX_KEY,
LTRIM(STUFF((SELECT N', ' + c.name
FROM sys.index_columns AS ic
JOIN sys.columns AS c
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
WHERE ic.object_id = i.object_id
AND ic.index_id = i.index_id
AND is_included_column = 1
ORDER BY c.name
FOR XML PATH(N'')), 1, 1,'')) AS INDEX_INCLUDE,
i.filter_definition AS INDEX_FILTER,
'FILL_FACTOR = ' + CAST(i.fill_factor AS VARCHAR(32)) +
', PAD_INDEX = ' + CAST(i.is_padded AS CHAR(1)) +
', ALLOW_ROWLOCK = ' + CAST(i.allow_row_locks AS CHAR(1)) +
', ALLOW_PAGELOCK = ' + CAST(i.allow_page_locks AS CHAR(1))
AS INDEX_WITH
FROM sys.indexes AS i
JOIN sys.objects AS o
ON i.object_id = o.object_id
JOIN sys.schemas AS s
ON o.schema_id = s.schema_id
JOIN sys.data_spaces AS ds
ON i.data_space_id = ds.data_space_id
LEFT OUTER JOIN sys.filegroups AS fg
ON ds.data_space_id = fg.data_space_id AND ds."type" = 'FG'
LEFT OUTER JOIN sys.partition_schemes AS ps
ON ds.data_space_id = ps.data_space_id AND ds."type" = 'PS'
LEFT OUTER JOIN sys.partition_functions AS pf
ON ps.function_id = pf.function_id
LEFT OUTER JOIN sys.xml_indexes AS xi
ON i.object_id = xi.object_id
AND i.index_id = xi.index_id
WHERE o.object_id = COALESCE(NULLIF(OBJECT_ID(@OBJ), 0), o.object_id)
AND i.index_id > 0
AND o.is_ms_shipped = 0
)
SELECT TABLE_NAME, INDEX_NAME, INDEX_TYPE, INDEX_STORAGE, INDEX_KEY,
CASE "type" WHEN 1 THEN '* - (INDEX_KEY)'
WHEN 5 THEN '*' END AS INDEX_INCLUDE,
INDEX_FILTER, INDEX_WITH
FROM T0
UNION ALL
SELECT s.name + '.' + o.name AS TABLE_NAME,
NULL AS INDEX_NAME, 'FULL TEXT' AS INDEX_TYPE,
'FULLTEXT CATALOG: ' + ftc.name AS INDEX_STORAGE,
NULL AS INDEX_KEY,
LTRIM(STUFF((SELECT N', ' + c.name
FROM sys.fulltext_index_columns AS ftic
JOIN sys.columns AS c
ON c.object_id = ftic.object_id
AND c.column_id = ftic.column_id
WHERE ftic.object_id = fti.object_id
FOR XML PATH(N'')), 1, 1,'')) AS INDEX_INCLUDE,
NULL AS INDEX_FILTER,
'CHANGE_TRACKING = ' + change_tracking_state_desc +
', STOPLIST = ' + CASE
WHEN fti.stoplist_id = 0 THEN 'SYSTEM'
WHEN fti.stoplist_id IS NULL THEN 'OFF'
ELSE (SELECT name
FROM sys.fulltext_stoplists AS ftsl
WHERE fti.stoplist_id = ftsl.stoplist_id)
END +
COALESCE(', SEARCH PROPERTY LIST = ' +
(SELECT name
FROM sys.registered_search_property_lists AS ftpl
WHERE fti.property_list_id = ftpl.property_list_id)
COLLATE French_BIN, '') AS INDEX_WITH
FROM sys.fulltext_indexes AS fti
JOIN sys.objects AS o
ON fti.object_id = o.object_id
JOIN sys.schemas AS s
ON o.schema_id = s.schema_id
JOIN sys.fulltext_catalogs AS ftc
ON fti.fulltext_catalog_id = ftc.fulltext_catalog_id
WHERE o.object_id = COALESCE(NULLIF(OBJECT_ID(@OBJ), 0), o.object_id)
ORDER BY TABLE_NAME, INDEX_KEY, INDEX_INCLUDE;
GO
EXEC sp_MS_marksystemobject 'sp__HELPINDEX';
Le code de la procédure à télécharger
(1) une procédure système est créée dans le schéma dbo de la base master et son nom doit commencer par ‘sp_’. Une foi marqué comme procédure système via la procédure système « sp_MS_marksystemobject », elle est appelable dans n’importe quelle base et se comporte comme une procédure locale.

Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
* Le site sur les SGBD relationnels et le SQL : https://sqlpro.developpez.com *
* le blog SQL, SQL Server, SGBDR... sur : https://blog.developpez.com/sqlpro/ *
* Expert Microsoft SQL Server, MVP (Most valuable Professional) depuis 14 ans *
* Entreprise SQL SPOT : modélisation, conseil, audit, optimisation, formation *
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
