Procédures et fonction de métadonnées des bases SQL Server – Partie 1

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`s table in all the databases of an instance         *
*******************************************************************************
* INPUTS :                                                                    *
*    @SCHEMA NVARCHAR(128) the name of the table`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 * * * * *

Ce contenu a été publié dans Procédure stockées de métadonnées, Procédures MS SQL Server, avec comme mot(s)-clé(s) , , , . Vous pouvez le mettre en favoris avec ce permalien.