Transact-Sql: la struttura di una tabella

La struttura di una tabella può essere recuperata con una (quasi) semplice istruzione Select: ovviamente il segreto è puntare alle tabelle giuste! E le cose possono cambiare a seconda dell’utente connesso al database.

Utente sa

Le informazioni sulle tabelle sono contenute in alcune tabelle di sistema, quelle il cui nome comincia con sys*: queste tabelle però sono accessibili soltanto utilizzando l’utente 'sa'.

Ad esempio, la tabella sysobjects riporta un record per ogni oggetto (tabella, vista, stored procedure, trigger o funzione) definito nel database; il campo xtype definisce il tipo di oggetto, perciò per limitare la ricerca alle sole tabelle utente basterà inserire una clausola Where xtype = 'u':

SELECT * FROM SysObjects WHERE xtype = 'u'

L’elenco completo dei tipi possibili è facilmente reperibile nei Books On Line, cercando proprio la parola sysobjects.

Volendo cercare informazioni riguardo ad una tabella specifica, basterà scrivere nella clausola Where il nome appropriato:

SELECT * FROM SysObjects WHERE [Name] = 'Clienti' AND [xtype] = 'u'

Allo stesso modo, la tabella syscolumns riporta le informazioni relative alle colonne che compongono le tabelle e le viste nel database; il legame tra syscolumns e sysobjects è instaurato attraverso il campo id nelle due tabelle.

Per quanto riguarda invece la definizione dei tipi di dato si deve fare riferimento alla tabella systypes: fin qui sembrerebbe tutto facile. Le cose però si complicano, ma solo leggermente, se consideriamo che nella definizione di una colonna possiamo usare uno dei tipi di dati predefiniti di Sql Server (quali int o datetime, ad esempio) oppure usare un tipo di dato definito dall’utente: ad esempio, per avere coerenza nel sistema potremmo definire un tipo di dato udtCodice a sua volta di tipo char(6).

In considerazione di ciò, per determinare il tipo utente che definisce una colonna la tabella systypes deve essere legata alla syscolumns tramite i rispettivi campi xusertype; per determinare invece il sottostante tipo nativo Sql occorre mettere in join la tabella systypes con sé stessa tramite i due campi xusertype e xtype.

Infine, la descrizione associata ad ogni colonna è reperibile nella tabella sysproperties che contiene i valori di tutte le proprietà definibile in un database Sql Server: in particolare, le descrizione delle colonne si trovano memorizzate con il nome 'MS_Description'.

Mettendo insieme i vari pezzi, otteniamo lo script:

DECLARE @NomeTabella AS VARCHAR(50)
 SET @NomeTabella = 'Clienti'

SELECT syscolumns.colorder AS 'Pos.'
     , syscolumns.name AS Colonna
     , systypes.name AS UDDT
     , B.Name AS Type
     , syscolumns.prec as 'Dim.'
     , CASE syscolumns.isnullable
            WHEN 1 THEN 'NULL'
            ELSE 'NOT NULL'
       END AS Nullable
     , CAST(ISNULL(sysproperties.[value], '') AS varchar(1000)) AS Descrizione
FROM sysobjects
INNER JOIN syscolumns
    ON sysobjects.id = syscolumns.id
INNER JOIN systypes
    ON syscolumns.xusertype = systypes.xusertype
INNER JOIN systypes B
    ON B.xusertype = systypes.xtype
LEFT OUTER JOIN sysproperties
    ON sysproperties.id = syscolumns.id
   AND sysproperties.smallid = syscolumns.colid
   AND sysproperties.name = 'MS_Description'
WHERE (sysobjects.xtype = 'U' )
  AND (sysobjects.name = @NomeTabella )
ORDER BY syscolumns.colorder

Utente non sa

Lo script precedente è utilizzabile soltanto accedendo al database in questione con l’utente 'sa'; come fare per determinare la struttura di una tabella se abbiamo a disposizione un utente con privilegi limitati? Ci vengono incontro le viste INFORMATION_SCHEMA.

Le viste INFORMATION_SCHEMA sono delle viste, residenti nel database master ed appartenenti all’utente INFORMATION_SCHEMA – appunto. Esse rimappano i valore delle tabelle di sistema e sono accessibili a tutti, in sola lettura. La vista che ci interessa si chiama COLUMNS la sua particolarità è che deve essere richiamata (analogamente alle altre viste della stessa famiglia) anteponendo il nome del proprietario, quindi INFORMATION_SCHEMA.COLUMNS.

Per riscrivere lo script precedente è necessario integrare le viste usando la funzione di sistema fn_listextendedproperty che restituisce la descrizione associata all’oggetto indicato dai parametri che le vengono passati (per l’elenco dei parametri si possono consultare i Books On Line). La funzione restituisce una tabella che può essere messa in join con la vista COLUMNS tramite il suo campo OBJNAME che deve corrispondere al campo COLUMN_NAME della vista.

A questo punto lo script può essere riscritto in questo modo:

DECLARE @NomeTabella AS VARCHAR(50)
SET @NomeTabella = 'CA_Profili'

SELECT ORDINAL_POSITION AS Pos
     , CAST(INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME AS VARCHAR(40)) AS 'Colonna'
     , INFORMATION_SCHEMA.COLUMNS.DOMAIN_NAME AS 'UDDT'
     , CAST(DATA_TYPE AS VARCHAR(15)) AS 'Tipo'
     , CHARACTER_MAXIMUM_LENGTH AS 'Dim.'
     , IS_NULLABLE AS 'Nullable'
     , CAST(ISNULL(COLUMN_DEFAULT, '') AS VARCHAR(12)) AS 'Default'
     , CAST(value AS VARCHAR(250)) as Descrizione
 FROM INFORMATION_SCHEMA.COLUMNS
 LEFT JOIN ::fn_listextendedproperty ('MS_Description', 'user', 'dbo', 'table', @NomeTabella, 'column', NULL)
 ON INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME = OBJNAME
 WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA = 'dbo'
 AND INFORMATION_SCHEMA.COLUMNS.TABLE_CATALOG = DB_NAME()
 AND INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = @NomeTabella
 ORDER BY Pos

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*